Reverse-sorting a Listview (with Comparer class)
I have a two-column ListView linked to a Datapager. The ListView lists all files of a particular type in a particular directory, so the data source is an ArrayList of type FileInfo. Consequently, I had to create a Comparer class to use in the ArrayList.Sort method.
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)
Retu开发者_StackOverflowrn 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)
All this works well, however, I don't know how to reverse the sort. As you can see from the code, I've determined the Sort Direction, but I don't know how to use it to reverse the sort.
Any thoughts?
I have usually done something like this:
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
If you don't want to use the System.Windows.Forms.SortOrder
, you can roll your own SortOrder enum. I usually prefer enums over booleans since you will get a clear statement in your code what the value means. Compare these two:
Dim comparer As New FileInfoDateComparer(True)
Dim comparer As New FileInfoDateComparer(SortOrder.Descending)
Have you Comparer classes include a Boolean member variable named something like SortAscending, and allow this value to be specified through the constructor.
For example, your FileInfoDateComparer class would look like the following (untested) code:
Class FileInfoDateComparer
Implements IComparer
Private _SortAscending As Boolean = True
Public Sub New(sortAscending As Boolean)
_SortAscending = sortAscending
End Sub
...
End Class
With that in place all that remains is to "swap" the oX and oY values before calling 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
That oughta do it! FYI, the above code was entered off the cuff, so there may be a syntax error in there, but the concept is sound - I've used it many times myself in past projects.
One final comment - if you are using .NET 3.5+ you can use LINQ to Objects syntax instead of having to create your own Comparer class, if you so desire...
Happy Programming...
You can send SortDirectory through your FileInfoDateComparer
; receiving an "DESC" value you can multiply return value by -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);
}
}
You said nothing about your framework version, but think about using Reverse()
Linq extension method.
精彩评论