Обратная сортировка списка (с классом 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.