Обратная сортировка списка (с классом Comparer) - PullRequest
1 голос
/ 07 октября 2009

У меня есть двухколонный ListView, связанный с Datapager. В ListView перечислены все файлы определенного типа в определенном каталоге, поэтому источником данных является ArrayList типа FileInfo. Следовательно, мне пришлось создать класс Comparer для использования в методе ArrayList.Sort.

FileInfoComparer.vb:

Imports System.IO

Friend Class FileInfoDateComparer
 Implements IComparer

 Public Overridable Overloads Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
  Dim oX As FileInfo = CType(x, FileInfo)
  Dim oY As FileInfo = CType(y, FileInfo)
  Return oX.LastWriteTime.CompareTo(oY.LastWriteTime)
 End Function
End Class

Friend Class FileInfoNameComparer
 Implements IComparer

 Public Overridable Overloads Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
  Dim oX As FileInfo = CType(x, FileInfo)
  Dim oY As FileInfo = CType(y, FileInfo)
  Return oX.Name.CompareTo(oY.Name)
 End Function
End Class

GenerateSortedArray sub:

 Private Sub GenerateSortedArray(ByVal SortColumn As String, ByVal SortDirection As String)
  Dim dirInfo As New DirectoryInfo(Server.MapPath(AppSettings.Item("ContentDir")))
  Dim FileArrayList As New ArrayList(dirInfo.GetFiles("*.msg", SearchOption.TopDirectoryOnly))

  With FileArrayList
   .TrimToSize()
   Select Case SortColumn
    Case "Name"
     .Sort(New FileInfoNameComparer)
    Case Else
     .Sort(New FileInfoDateComparer)
   End Select
  End With

ListView_Sorting:

  Session("SortColumn") = e.SortExpression
  Session("SortDirection") = e.SortDirection

  Call GenerateSortedArray(e.SortExpression, DBNull.Value.ToString)

Все это работает хорошо, однако я не знаю, как изменить сортировку. Как вы можете видеть из кода, я определил направление сортировки, но я не знаю, как использовать его для реверсирования сортировки.

Есть мысли?

Ответы [ 3 ]

1 голос
/ 07 октября 2009

Вы можете отправить SortDirectory через ваш FileInfoDateComparer; получив значение "DESC", вы можете умножить возвращаемое значение на -1;

// sorry, C# version:

class FileInfoDateComparer
{
    private bool ascendingOrder = true;
    public FileInfoDateComparer(bool ascendingOrder)
    {
        this.sortOrder = sortOrder;
    }

    ... int Compare(object x, object y)
    {
        //...
        return
            oX.LastWriteTime.CompareTo(oY.LastWriteTime) * 
            (ascendingOrder ? 1: -1);
    }

}

Вы ничего не сказали о своей версии фреймворка, но подумайте об использовании Reverse() метода расширения Linq.

1 голос
/ 07 октября 2009

Я обычно делал что-то вроде этого:

Friend Class FileInfoDateComparer
 Implements IComparer

    Private _sortOrder As System.Windows.Forms.SortOrder

    Public Sub New(ByVal sortOrder As System.Windows.Forms.SortOrder)
        _sortOrder = sortOrder
    End Sub

    Public Overridable Overloads Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
       Dim oX As FileInfo = CType(x, FileInfo)
       Dim oY As FileInfo = CType(y, FileInfo)
       Dim result As Integer = oX.LastWriteTime.CompareTo(oY.LastWriteTime)
       If _sortOrder = System.Windows.Forms.SortOrder.Descending Then
           ' we want the reverse sort order, so we "reverse" the result '
           result = result * -1
       End If
       Return result
 End Function
End Class

Если вы не хотите использовать System.Windows.Forms.SortOrder, вы можете бросить свой собственный список SortOrder. Я обычно предпочитаю enums, а не booleans, поскольку в вашем коде вы получите четкое утверждение о том, что означает это значение. Сравните эти два:

Dim comparer As New FileInfoDateComparer(True)
Dim comparer As New FileInfoDateComparer(SortOrder.Descending)
1 голос
/ 07 октября 2009

Есть ли у классов Comparer логическая переменная-член с именем типа SortAscending, и она позволяет указывать это значение в конструкторе.

Например, ваш класс FileInfoDateComparer будет выглядеть следующим (непроверенным) кодом:

Class FileInfoDateComparer
 Implements IComparer

  Private _SortAscending As Boolean = True

  Public Sub New(sortAscending As Boolean)
    _SortAscending = sortAscending
  End Sub

  ...
End Class

После этого остается только поменять местами значения oX и oY перед вызовом CompareTo IF SortAscending = False.

Public Overridable Overloads Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
  Dim oX As FileInfo = CType(x, FileInfo)
  Dim oY As FileInfo = CType(y, FileInfo)

  If _SortAscending = False Then
    Dim temp As FileInfo = oX
    oX = oY
    oY = temp
  End If

  Return oX.LastWriteTime.CompareTo(oY.LastWriteTime)
End Function

Это нужно сделать! К вашему сведению, вышеприведенный код был введен с манжеты, поэтому там может быть синтаксическая ошибка, но концепция обоснована - я сам много раз использовал ее в прошлых проектах.

Один последний комментарий - если вы используете .NET 3.5+, вы можете использовать синтаксис LINQ to Objects вместо того, чтобы создавать собственный класс Comparer, если вы этого хотите ...

Счастливое программирование ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...