Introduction
So I hope I do not have to explain how IComparer
works... just a very quick briefing for those who are not aware.
Most collections and controls of VB.NET give the possibility to define an own control logic. For example, if you want to sort an arraylist that contains other small arrays, you can implement your logic and define that he has to compare the first and the second element of the "jagged" array. Otherwise, if you are a very good coder, but I think you are not going to read this article, you can decide to sort for shades of red some pictures. This is not the case, I would just implement an efficient routine to sort alphanumerically so that the item "WPS-9" is smaller than "WPS-10". This should not be true with the default sorter of .NET.
Using the Code
The controls and classes have a method to implement the Icomparer
:
TreeView1.TreeViewNodeSorter=new TreeSorter
LisView1.ListViewItemSorter
You have just to build a class that implements that Interface Icompare
(you need just to write Implements IComparer
under the declaration of the class) and this class must implement the method Compare
(you need just to specify after the declaration of the function Implements Icomparer.Compare
).
And here is the algorithm:
Public Class TreeSorter
Implements System.Collections.IComparer
Private obcomparer As New CaseInsensitiveComparer
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
Implements System.Collections.IComparer.Compare
Dim tx As TreeNode = CType(x, TreeNode)
Dim ty As TreeNode = CType(y, TreeNode)
Dim nx, ny As New System.Text.StringBuilder
Dim cx(), cy() As Char
cx = tx.Text.ToLower.ToCharArray
cy = ty.Text.ToLower.ToCharArray
If tx.Text.Length = 0 Then Return -1
If ty.Text.Length = 0 Then Return 1
Dim xl, yl, i, j As Integer
xl = UBound(cx)
yl = UBound(cy)
Dim tempX, tempY As Integer
Do
Do While i <= xl AndAlso Char.IsDigit(cx(i))
nx.Append(cx(i))
i += 1
Loop
Do While j <= yl AndAlso Char.IsDigit(cy(j))
ny.Append(cy(j))
j += 1
Loop
If nx.Length > 0 Then
If ny.Length = 0 Then Return -1
tempX = Convert.ToInt32(nx.ToString)
tempY = Convert.ToInt32(ny.ToString)
If tempX > tempY Then Return 1
If tempX < tempY Then Return -1
If i > xl Then
If j > yl Then Return 0
Return -1
End If
If j > yl Then Return 1
nx = New System.Text.StringBuilder
ny = New System.Text.StringBuilder
End If
If ny.Length > 0 Then Return 1
If cx(i) <> cy(j) Then Return String.Compare(cx(i), cy(j))
If i < xl Then
i += 1
If j < yl Then
j += 1
Else
Return 1
End If
Else
If j < yl Then
Return -1
Else
Return 0
End If
End If
Loop
End Function
End Class
Points of Interest
It is fast. It compares the string
s char
by char
, so at the first difference it returns instantly. Enjoy it.