I have a custom collection that inherits from BindingList.
I bind it to a WinForms DataGridView and want to provide sorting by clicking
the column headers. It does not work right away and I found out it is because
the collection does not support Sorting in itself.
I read that I need to override ApplySortCore, RemoveSortCore and
SupportsSortingCore.
But how do I do that? I searched MSDN and NewGroups but found no straight
example.
I finally found an example and applied it successfully.
I enclose my code here if someone else needs it.
This is the region I added to my collection class:
#Region " Provide sorting capability to BindingList "
Private m_SortProperty As PropertyDescriptor = Nothing
Private m_SortDirection As ListSortDirection =
ListSortDirection.Ascending
Private m_IsSorted As Boolean
Private m_OriginalCollection As List(Of Customer) = New List(Of
Customer)
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return m_IsSorted
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As
ListSortDirection
Get
Return m_SortDirection
End Get
End Property
Protected Overrides ReadOnly Property SortPropertyCore() As
PropertyDescriptor
Get
Return m_SortProperty
End Get
End Property
Protected Overrides Sub ApplySortCore(ByVal prop As
PropertyDescriptor, ByVal direction As ListSortDirection)
m_SortDirection = direction
m_SortProperty = prop
'Store the original order of the collection
If (m_OriginalCollection.Count = 0) Then
m_OriginalCollection.AddRange(Me)
End If
Dim listRef As List(Of Customer) = DirectCast(Me.Items, List(Of
Customer))
If IsNothing(listRef) Then Return
'Let List(Of Customer) do the actual sorting based on your
comparer
Dim comparer As SortComparer(Of Customer) = New SortComparer(Of
Customer)(prop, direction)
listRef.Sort(comparer)
m_IsSorted = True
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Public Shadows Sub RemoveSortCore()
If m_IsSorted Then
Me.Clear()
For Each item As Customer In m_OriginalCollection
Me.Add(item)
Next
m_OriginalCollection.Clear()
m_SortProperty = Nothing
m_IsSorted = False
End If
End Sub
Class SortComparer(Of Customer)
Implements IComparer(Of Customer)
Private m_PropDesc As PropertyDescriptor
Private m_Direction As ListSortDirection
Public Sub New(ByVal propDesc As PropertyDescriptor, ByVal
direction As ListSortDirection)
m_PropDesc = propDesc
m_Direction = direction
End Sub
Public Function Compare(ByVal x As Customer, ByVal y As
Customer) As Integer Implements IComparer(Of Customer).Compare
Dim xValue As Object = m_PropDesc.GetValue(x)
Dim yValue As Object = m_PropDesc.GetValue(y)
Return CompareValues(xValue, yValue, m_Direction)
End Function
Private Function CompareValues(ByVal xValue As Object, ByVal
yValue As Object, ByVal direction As ListSortDirection) As Integer
Dim retValue As Integer
If (TypeOf xValue Is IComparable) Then
retValue = DirectCast(xValue,
IComparable).CompareTo(yValue)
ElseIf (TypeOf yValue Is IComparable) Then
retValue = DirectCast(yValue,
IComparable).CompareTo(xValue)
ElseIf xValue.Equals(yValue) Then
retValue = 0
Else
retValue = xValue.ToString().CompareTo(yValue.ToString())
End If
If (direction = ListSortDirection.Ascending) Then
Return retValue
Else
Return retValue * -1
End If
End Function
End Class
#End Region