VB.NET: How to sort listview by clicked column
One of my favorite .NET control is the ListView. It is very useful for displaying multiple records on a spreadsheet format. Column sorting is one the feature of spreadsheet applications that most of end-users are used to. Unfortunately, this is not readily available as property in VB.NET. The ListView Sorting property only sorts items and not the sub-items so it can’t be use if we want to allow the user to sort your list by any clicked column.
To make your ListView application capable of column sorting, follow these steps:
1. On your existing project, add a new class with following code:
Imports System.Collections
Public Class clsListviewSorter
Implements System.Collections.IComparer ' Implements a comparer Implements IComparer
Private m_ColumnNumber As Integer
Private m_SortOrder As SortOrder
Public Sub New(ByVal column_number As Integer, ByVal sort_order As SortOrder)
m_ColumnNumber = column_number
m_SortOrder = sort_order
End Sub
' Compare the items in the appropriate column
Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
Dim item_x As ListViewItem = DirectCast(x, ListViewItem)
Dim item_y As ListViewItem = DirectCast(y, ListViewItem)
' Get the sub-item values.
Dim string_x As String
If item_x.SubItems.Count <= m_ColumnNumber Then
string_x = ""
Else
string_x = item_x.SubItems(m_ColumnNumber).Text
End If
Dim string_y As String
If item_y.SubItems.Count <= m_ColumnNumber Then
string_y = ""
Else
string_y = item_y.SubItems(m_ColumnNumber).Text
End If
' Compare them.
If m_SortOrder = SortOrder.Ascending Then
If IsNumeric(string_x) And IsNumeric(string_y) Then
Return (Val(string_x).CompareTo(Val(string_y)))
ElseIf IsDate(string_x) And IsDate(string_y) Then
Return (DateTime.Parse(string_x).CompareTo(DateTime.Parse(string_y)))
Else
Return (String.Compare(string_x, string_y))
End If
Else
If IsNumeric(string_x) And IsNumeric(string_y) Then
Return (Val(string_y).CompareTo(Val(string_x)))
ElseIf IsDate(string_x) And IsDate(string_y) Then
Return (DateTime.Parse(string_y).CompareTo(DateTime.Parse(string_x)))
Else
Return (String.Compare(string_y, string_x))
End If
End If
End Function
End Class
2. Declare a private variable on the form where the listview you want to be sorted is located.
Private m_SortingColumn As ColumnHeader
3. Then on the listview’s ColumnClick event, add the following code
Private Sub ListView1_ColumnClick(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnClickEventArgs) Handles ListView1.ColumnClick
' Get the new sorting column.
Dim new_sorting_column As ColumnHeader = ListView1.Columns(e.Column)
' Figure out the new sorting order.
Dim sort_order As System.Windows.Forms.SortOrder
If m_SortingColumn Is Nothing Then
' New column. Sort ascending.
sort_order = SortOrder.Ascending
Else ' See if this is the same column.
If new_sorting_column.Equals(m_SortingColumn) Then
' Same column. Switch the sort order.
If m_SortingColumn.Text.StartsWith("> ") Then
sort_order = SortOrder.Descending
Else
sort_order = SortOrder.Ascending
End If
Else
' New column. Sort ascending.
sort_order = SortOrder.Ascending
End If
' Remove the old sort indicator.
m_SortingColumn.Text = m_SortingColumn.Text.Substring(2)
End If
' Display the new sort order.
m_SortingColumn = new_sorting_column
If sort_order = SortOrder.Ascending Then
m_SortingColumn.Text = "> " & m_SortingColumn.Text
Else
m_SortingColumn.Text = "< " & m_SortingColumn.Text
End If
' Create a comparer.
ListView1.ListViewItemSorter = New clsListviewSorter(e.Column, sort_order)
' Sort.
ListView1.Sort()
End Sub
There you have it, test your listview application and it should be sorting by the column clicked.
3 comments
Leave a Reply
You must be logged in to post a comment.
thanks!
excelllent explanation !
Thank you Ray for the help, i really appreciate finding this.