To make your ListView application capable of column sorting, follow these steps:
1. On your existing project, add a new class with following code:
Public Class clsListviewSorter ' 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 System.Collections.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 System.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.
Download the sample VB.NET 2008 project
For more VB.NET tips and tricks, subscribe now
33 comments:
Good stuff. Works like a charm.
Keep up the good work mate.
I almost lost all my hair pondering over this problem. All solutions were either very slow, or didn't work properly, or (mostly) both.
And your solution works with alphabet values AND numerical ones (Wow !!!)
Many thanks, mate !
Works great - just what I needed and concise. Also, I like that it does not error out when sorting on a date column and a record has no date in it. Very good. Thanks!
Murf
Yes, this works well. However, I made a small change.
Even though we can sort any column, listview will only search on the first column. To get around this I made the first column zero width, so it doesn't display. Then in the listview column click event I added code at the end of the procedure to copy the contents of the selected column to the first column.
When I enter some characters, the listview looks like it is searching on the selected column. In actual fact it is sorting on the hidden first column, which has the same contents as the selected column.
I don't know why everyone gives such great comments. Paste that code into a new class and you get 12 compile errors. I'm sure its great code but please try and preserve line spacing, and there seems to be missing import statements.
@joel - i added it modified this post to help you more.
Thanks alot for the code sample. I had a very similar version using ICompare, but it only sorted text, and didn't properly sort positive and negative numbers. Yours works great.
Hi this is not working on VS 2008
In the class im getting error on this line "Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare"
ERROR : "Error 3 Interface 'System.Collections.IComparer' is not implemented by this class. D:\=VB Projects=\LoadFilesManager\LoadFilesManager\clsListViewSorter.vb 10 89 LoadFilesManager
"
Please any help would be great.
Thx Mike
@mike
--your missing the following line
Implements System.Collections.IComparer.Compare
I already adjusted the code above to make it copy and paste friendly
thanks :)
I'm also getting some errors in VS2008
__________________
Error 1 Class 'clsListviewSorter' must implement 'Function Compare(x As Object, y As Object) As Integer' for interface 'System.Collections.IComparer'.
__________________
Error 2 Statement is not valid inside a method.
__________________
Any help would be kind of you.
Thanks
@michael
I included a sample VB.NET 2008 project for your reference.
Thanks!
Finally a tutorial on sorting the listview component that works! Thank you :)
Im using VS 2008 and it works like a charm, keep up the good work.
Fryan; Thank you for the project file.
I'm using WinXP Pro and VS2008 VB.NET
Follow the 3 steps instruction, copy and paste, it works perfectly. Good job!
Thank you.
Great work thanks. Worked first go.
Thanks for this - grand stuff
Hey dude, Thanks a lot.
I'm using the code in a project i'm workin on, and i had this problem to solve.
tnx fv
Wow - works as advertised!
Thank you!
Thank u dude!
>jboy
Hey there,
thank you very much for this piece of code. It works like a charm.
I have only one problem... when I refresh the data, in the listview I just sorted, my application freezes.
You have any idea how I could solve this problem? Maybe reset the sorting order to nothing?
Works great!!! Thanks!
Great work, my days work has been reduced to few mins (to copy/paste and do few modifications as per my need). Keep up the great work and thanks for sharing the code.
Excellent job my friend...
ok...that was way to easy! thanks heraps for posting this code :)
this is not simple enough?
If Listview1.Sorting = Windows.Forms.SortOrder.Ascending Then
Listview1.Sorting = Windows.Forms.SortOrder.Descending
Else
Listview1.Sorting = Windows.Forms.SortOrder.Ascending
End If
Listview1.Sort()
thanks.. it's works great
Very much thanks bro..It works great. Hoping for more tips and tricks for vb.net. Your helping bro..Just keep it up and more blessings to come.
What's nice about the class is you can modify it to sort by more then just the data in the column you are clicking. I have a column of scores and one with user ages, now instead of just sorting by scores it also compares the age so when scores are tied the younger age trumps the elders, you just can't do stuff like that using the normal LV sort. Thanks!!!
Thanks man. Works very good..
BIG Thanks, I really looking for this for a loooong time :)
If you run into trouble regarding missing subitems when you switch the contents of the listview.. add this to the bottom of the column-click-event-code:
ListView1.ListViewItemSorter = nothing
(right after listview1.sort())
Thank you so much, your code was very helpful!
Post a Comment