Обратная сортировка списка (с классом Comparer)

У меня есть два столбца 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 ответа

Решение

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

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. Я обычно предпочитаю перечисления, а не логические, поскольку в вашем коде вы получите четкое утверждение о том, что означает это значение. Сравните эти два:

Dim comparer As New FileInfoDateComparer(True)
Dim comparer As New FileInfoDateComparer(SortOrder.Descending)

У вас есть классы 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, если вы этого хотите...

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

Вы можете отправить 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.

Другие вопросы по тегам