Introduction
WPF is a whole new technology to build rich user interfaces. The whole ambit of controls also provides for an easier development experience. Recently we came across an issue where we had a WPF ListView for our grid screens and which was bound to an ADO.NET dataset. The grid afforded the user the capability to sort, filter and other operations. However all fields were being sorted as text values. This threw an issue when trying to sort a column with integer values
Background
Normal sorting for an ADO.NET bound ListView uses the default sorting behavior treating all data as strings. Sample code for the same follows.
Dim lv as ListView ‘assume you already have a ListView reference which is lv
Dim myView as ICollectionView = CollectionViewSource.GetDefaultView (lv.ItemsSource)
Dim mySortColumn as string = "sortcolumn" ‘Let mySortColumn let be name of column to sort on
myView.SortDescriptions.Add (new sortdescription (mySortColumn, ListSortDirection.Ascending)
myView.Refresh ()
This is the default way to sort a ListView by a column say ‘sortcolumn’ above. However what do you do when you want to perform some custom sorting on the ListView according to your own custom logic?
Solution & Code
A good reference to the behavior of WPF ListViews can be found in the article here
With reference to the article above if the binding source implements IList then you can cast the ICollectionView
above to a ListCollectionView.ListCollectionView
has a Customsort Property which you can assign an instance of your custom sort class which implements IComparable
.
However if you have bound the ListView to an instance of IBindingList
for e.g. a Dataview then ICollectionView
above is a case of BindingListCollectionView
which does not have a custom sort property. This view delegates the logic for sorting , filtering etc to the underlying dataview.
To implement custom sorting we thus made use of the underlying dataview which can be obtained by
Dim myDataView as DataView = TryCast (myView.SourceCollection, DataView)(myView is of type ICollectionView as above)
Now create a class which implements IComparable and which will have your custom sorting logic. This class should have a overridden ToString method which returns the custom ToString representation for the class and should implement the CompareTo
method. An example is below.
Public class CustomComparer
Implements IComparable
Private _Value as Object ‘This is the internal value stored in the class
Public function CompareTo (value as Object) as Integer implements IComparable. CompareTo
Put your custom sorting logic here
End function
Public overrides function ToString () as String
End function
End Class
Now add a new column to the underlying datatable for the bound dataview which is of the type of the class above and add a new instance of this class for each DataRowView of the dataview for the new column..Ie.
‘ Pseudo code
For each row as DataRowView in myView
Dim myNewClass as New CustomComparer()
Row(myNewColumnName) = myNewClass
Next
Next perform the same logic as above for the sorting except that for the sorting column add the new column that you have added above instead of the actual column,i.e,
Dim mySortColumn as string = "sortcolumn" ‘Where mySortColumn is the name of column just added to the view above.
myView.SortDescriptions.Add (new sortdescription (mySortColumn, ListSortDirection.Ascending)
myView.Refresh ()
The view will now sort by the new column supplied and will call the CompareTo method of your custom class, i.e. CustomComparer above to perform the sorting.
Wrapping it Up
Custom Sorting can be a common requirement for grid controls. While I make no claims as to this being the only solution to the problem above this was a simple solution which got us the desired effect.
Note : Please note that the code above is just meant to give an idea of the implementation details to the user and is mostly pseudocode( using VB.NET syntax). Please develop the code in full from the examples above in your development IDEs.