This is a short bit of code that shows how to implement sorting on columns in a details-mode ListView. Suggestions for improvement are always welcome. One possible improvement would be to modify the column headers to indicate which column is being sorted and in which direction.
ListView Column Sort Demo
'
' Name:
'
' ListViewSortDemo
'
' Description:
'
' Demo code to show how to sort by clicking on a ListView column.
'
' Notes:
'
' To create the form for this project you only have to add a ListView control
' to a blank form. Put the listview into details mode and add four columns.
' Set the widths of all columns to 100. Set the font to Courier New (or some
' other monospaced font). All listview entries for this demo are added at run
' time.
'
' I keep track of the current sort order by using the Tag property of each
' column. I use +1 and -1 because it is so easy to toggle.
'
' In order to sort you must create a custom class that implements the IComparer
' interface. It will have one method named Compare which will return one of
' three values indicating the result of the comparison. If you are sorting from
' smallest to largest then the values returned are:
'
' -1 - item1 < item2
' 0 - item1 = item2
' +1 - item1 > item2
'
' If you are sorting from largest to smallest then reverse the signs.
'
' The Compare function need not be restricted to one column or be based on a
' strict numerical or string comparison. This demo uses three custom compare
' classes.
'
' NumericSorter
'
' Sorts all rows based on the integer values in column 1
'
' SumSorter
'
' Sorts all rows based on the sums of the digits in column 2
'
' NameSorter
'
' Does a two column sort. It sorts all rows based on the string value in
' column 3, then the string value in column 4.
'
' Audit:
'
' 2012-08-12 Reverend Jim original code
'
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'Keep track of the last selected sort order using the Tag property
For Each col As Object In ListView1.Columns
col.tag = -1
Next
'populate a four column listview with some data
AddRow(ListView1, {"87013", "87013", "Fred", "Stalder"})
AddRow(ListView1, {"90215", "90215", "Virgil", "Samms"})
AddRow(ListView1, {"600021", "600021", "Rod", "Kinnison"})
AddRow(ListView1, {"2457", "2457", "Fred", "Flintstone"})
AddRow(ListView1, {"7259", "7259", "Nils", "Bergenholm"})
End Sub
Private Sub AddRow(lvw As ListView, data() As String)
'add a row to the given listview
Dim item As New ListViewItem()
item.Text = data(0)
For i As Integer = 1 To UBound(data)
item.SubItems.Add(data(i))
Next
lvw.Items.Add(item)
End Sub
Private Sub ListView1_ColumnClick(sender As System.Object, e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
Dim lvw As ListView = sender
'sort on the clicked column
Select Case e.Column
Case 0 : lvw.ListViewItemSorter = New NumericSorter
Case 1 : lvw.ListViewItemSorter = New SumSorter
Case 2 : lvw.ListViewItemSorter = New NameSorter(2, 3)
Case 3 : lvw.ListViewItemSorter = New NameSorter(3, 2)
End Select
'Toggle sort order
lvw.Sorting = IIf(lvw.Columns(e.Column).Tag = -1, SortOrder.Ascending, SortOrder.Descending)
lvw.Columns(e.Column).Tag *= -1
End Sub
Class NumericSorter 'sorts on the first column based on the numeric value
Implements IComparer
Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
Dim item1 As ListViewItem = x
Dim item2 As ListViewItem = y
If item1.ListView.Sorting = SortOrder.Ascending Then
Return Math.Sign(CInt(item1.SubItems(0).Text) - CInt(item2.SubItems(0).Text))
Else
Return -Math.Sign(CInt(item1.SubItems(0).Text) - CInt(item2.SubItems(0).Text))
End If
End Function
End Class
Class SumSorter 'sorts on the second column based on the sum of the digits
Implements IComparer
Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
Dim item1 As ListViewItem = x
Dim item2 As ListViewItem = y
Dim sum1 As Integer = 0
Dim sum2 As Integer = 0
For Each ch As Char In item1.SubItems(1).Text.ToCharArray
sum1 += Val(ch)
Next
For Each ch As Char In item2.SubItems(1).Text.ToCharArray
sum2 += Val(ch)
Next
If item1.ListView.Sorting = SortOrder.Ascending Then
Return Math.Sign(sum1 - sum2)
Else
Return -Math.Sign(sum1 - sum2)
End If
End Function
End Class
Class NameSorter 'sorts on the two columns given in the constructor
Implements IComparer
Private _columns() As Integer
Public Sub New(column1 As Integer, column2 As Integer)
_columns = {column1, column2}
End Sub
Public Function Compare(x As Object, y As Object) As Integer Implements System.Collections.IComparer.Compare
Dim item1 As ListViewItem = x
Dim item2 As ListViewItem = y
Dim text1 As String = item1.SubItems(_columns(0)).Text & item1.SubItems(_columns(1)).Text
Dim text2 As String = item2.SubItems(_columns(0)).Text & item2.SubItems(_columns(1)).Text
If item1.ListView.Sorting = SortOrder.Ascending Then
Return StrComp(text1, text2)
Else
Return -StrComp(text1, text2)
End If
End Function
End Class
End Class
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.