Browse DevX
Sign up for e-mail newsletters from DevX


Add Flexible Sort Capabilities to ListView Controls : Page 2

Learn how to make the ListView control sort by a column when a user clicks on a column header, sort by all columns, or sort in just about any other way you can imagine.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Using the SelectedColumnSorter Class
The SortableListView control can now use the SelectedColumnSorter class to sort its items by a particular column. The code fragment in Listing 1 shows key pieces of the SortableListView control. For simplicity, I've omitted the code that's not related to sorting by a selected column.

After importing the System.ComponentModel namespace, the code in Listing 1 includes a ToolboxBitmap attribute and the Class statement that indicates the control inherits from ListView:

<ToolboxBitmap(GetType(SortableListView), _ "tbxSortableListView")> _ Public Class SortableListView

The control defines the SortStyles enumeration so you can indicate whether the control should sort using the default method, by all columns, or by a selected column:

Public Enum SortStyles SortDefault SortAllColumns SortSelectedColumn End Enum

It also declares the variable m_SelectedColumn to hold the index of the column on which it should be sorting.

The SortStyle property gets and sets a SortStyles value. The Get procedure simply returns the value saved in variable m_SortStyle:

Public Property SortStyle() As SortStyles Get Return m_SortStyle End Get ...

The Set procedure shown in Listing 1 performs a little more work. First it checks whether the control is currently sorting by a selected column. If it is, then the code removes the sort indicator arrow by setting the column's ImageKey property to Nothing so the column doesn't display any image:

Set(ByVal value As SortStyles) ' If the current style is SortSelectedColumn, ' remove the column sort indicator. If m_SortStyle = SortStyles.SortSelectedColumn Then If m_SelectedColumn >= 0 Then Me.Columns(m_SelectedColumn).ImageKey = Nothing m_SelectedColumn = -1 End If End If ...

Next, the Set procedure saves the new sort style and then uses a Select Case statement to take appropriate action. When the new sort style is SortDefault, the code sets the ListViewItemSorter property to Nothing so the ListView's default sorting behavior takes over. When the sort style is SortAllColumns, the code sets the ListViewItemSorter property to a new AllColumnSorter object (described in the next section). When the new style is SortSelectedColumn, then the code sets the ListViewItemSorter property to a new SelectedColumnSorter object:

... ' Save the new value. m_SortStyle = value Select Case m_SortStyle Case SortStyles.SortDefault Me.ListViewItemSorter = Nothing Case SortStyles.SortAllColumns Me.ListViewItemSorter = New AllColumnSorter() Case SortStyles.SortSelectedColumn Me.ListViewItemSorter = _ New SelectedColumnSorter() End Select ' Resort. ' Me.Sort() End Set End Property

At this point, the Set procedure could call the control's Sort method to resort the items using the new sorter. I found that confusing in the example program so I commented out the code and let the main program call the control's Sort method explicitly.

The last piece of the control's code needed for column sorting is the OnColumnClick method, called whenever the user clicks on a column header. The code starts by calling the base class's OnColumnClick method. It then determines whether the current sorting style is SortSelectedColumn:

Protected Overrides Sub OnColumnClick( _ ByVal e As System.Windows.Forms.ColumnClickEventArgs) MyBase.OnColumnClick(e) If Me.SortStyle = SortStyles.SortSelectedColumn Then ' If this is the same sort column, switch the sort order. If e.Column = m_SelectedColumn Then If Me.Sorting = SortOrder.Ascending Then Me.Sorting = SortOrder.Descending Else Me.Sorting = SortOrder.Ascending End If End If ' Remove the image from the previous sort column. If m_SelectedColumn >= 0 Then Me.Columns(m_SelectedColumn).ImageKey = Nothing End If ' If we're not currently sorting, sort ascending. If Me.Sorting = SortOrder.None Then Me.Sorting = SortOrder.Ascending End If ' Save the new sort column and give it an image. m_SelectedColumn = e.Column If Me.Sorting = SortOrder.Descending Then Me.Columns(m_SelectedColumn).ImageKey = _ "sortDescending.bmp" Else Me.Columns(m_SelectedColumn).ImageKey = _ "sortAscending.bmp" End If ' Resort. Me.Sort() End If End Sub

When a user clicks the same column that was selected previously, the OnColumnClick code shown switches the control's sort order, and clears the sort indicator arrow. If there's no current sort-order selection, the code uses the default ascending order.

The code then saves the newly clicked column as the selected column and sets the appropriate sort order indicator arrow for the column.

Author's Note: Your main program should set the control's SmallImageList property to an ImageList control that contains these images. Their names in the ImageList should be sortDescending.bmp and sortAscending.bmp. I've found that 16 x 14 pixel images seem to look the best.

Finally, the OnColumnClick code calls the control's Sort method to resort the items based on the newly selected column and sort order.

Thanks for your registration, follow us on our social networks to keep up-to-date