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.