I am filling a ListView control with information from the file system (file name, file size, and file date) and I'd like to be able to sort on any of the columns. I'd like to have the control work like Windows Explorer -- that is, if I click once on a column, the data sorts in ascending order, and if I click again, the data sorts in descending order. I can't even figure out how to get the data to sort, much less how to get it to sort in various directions. Help!
-- Randi
Yes, this is much harder than you might otherwise think. The Sort method of the ListView control sorts only on the first column, and uses the Sorting property to determine the direction of the sort. This works great if you're displaying data in a view other than Details view, but when you're displaying multiple columns, it doesn't help much.
To get started following this explanation, follow these steps. First, create a new Windows application project, and add a ListView control to Form1. (You'll probably want to set the ListView control so that it docks to fill the parent container.) Double-click the form to create its Load event handler. At the top of the class, add an Imports statement, importing System.IO. Within the Form_Load procedure, add the following code:
' Create the columns
ListView1.Columns.Clear()
ListView1.Columns.Add("Filename")
ListView1.Columns.Add("Size")
ListView1.Columns.Add("Creation Date")
ListView1.View = View.Details
' Fill the columns:
Dim di As New DirectoryInfo("C:\")
For Each fi As FileInfo In di.GetFiles()
Dim item As ListViewItem = ListView1.Items.Add(fi.Name)
item.SubItems.Add(fi.Length.ToString)
item.SubItems.Add(fi.CreationTime.ToShortDateString())
Next
' Resize the columns:
For Each col As ColumnHeader In ListView1.Columns
col.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
Next
This code first clears the Columns collection, creates the new columns, and sets the view for the ListView control. The code then iterates through all the files in C:\, and adds information about each to the ListView. Finally, the code resizes each column appropriately. Run the project, and verify that you see all the files from the C:\ folder.
In order to sort columns based on clicking, you'll react to the ListView control's ColumnClick event. To try it out, add the following code to the control's ColumnClick event handler (select the control in the designer, and in the Properties window, double-click on the ColumnClick event):
If ListView1.Sorting = SortOrder.Ascending Then
ListView1.Sorting = SortOrder.Descending
Else
ListView1.Sorting = SortOrder.Ascending
End If
Run the project, and try clicking any column -- the data sorts based on file name. Click again, and it sorts descending. In order to sort on any other column, you'll need to supply your own ListViewItemSorter instance. This class, which implements IComparer, lets you control the ordering of the items in the ListView control. The IComparer interface includes a single procedure, named Compare, which compares two items of the same type. You'll need to create a separate comparer for each type you want to sort. In this case, you'll need one for Long values, one for DateTime values, and one for String values. They're all generally the same, however, so once you've written one, the rest are easy.