I have a ListView (GridView) that I want to sort by 2 columns, so if 2+ items have the same value in Column 1, it sorts by Column 2. Pretty easy. But empty strings show up at the top when sorting A-Z. I'd like to move them to the bottom. I made a comparer (IComparer) that takes care of this, but I'm not sure how to use it.
Here's the code I tried:
Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection)
Using view.DeferRefresh
view.SortDescriptions.Clear()
view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction))
view.SortDescriptions.Add(New SortDescription(otherColumn, direction))
view.CustomSort = New MyComparer()
End Using
The problem is my comparer is given a type of my class instead of the value of the property/column being sorted by. So if the class is Foo and I'm sorting by Foo.Bar, I get the entire Foo class, not just the value of Bar (which is really all it should be concerned about, since that's what it's sorting by).
How will my comparer know which property to compare? Maybe I'm doing something wrong here, because this doesn't make any sense. I expected to get a String (the property type) for x and y...
Does anyone know how to do this?
Your IComparer
implementation will be given the entire object, you need to figure out which column gets clicked, probably by doing something like this:
this.AddHandler(GridViewColumnHeader.ClickEvent,
new RoutedEventHandler(Column_Sort));
and then feed that into your MyComparer
probably by modifying your constructor to take in the property path.
In Column_Sort
you can get the property path something like this (I'm a little rusty on vb, but c# would do this:
void Column_Sort(object sender, RoutedEventArgs e)
{
var memberBinding= ((GridViewColumnHeader)e.OriginalSource).Column.DisplayMemberBinding;
var path = ((Binding)memberBinding).Path.Path;
}
and then feed that into your sorting logic.
Dim view As ListCollectionView = CollectionViewSource.GetDefaultView(myCollection)
Using view.DeferRefresh
view.SortDescriptions.Clear()
view.SortDescriptions.Add(New SortDescription(sortHeader.Header, direction))
view.SortDescriptions.Add(New SortDescription(otherColumn, direction))
view.CustomSort = New MyComparer(PropertyPath)
End Using
EDIT:
You just need to customize your IComparer
to support multiple column sorting, I googled and found this comparer implementation that you can feed it several property paths separated by commas and suffixed with ASC/DESC like this:
User.LastName DESC, User.FirstName DESC
I think the convention for multi-column sorting as far as UI is concerned is that you need to have the Ctrl
button held. So subclass the ListView class and tie into the GridViewColumnHeader clicked event and the KeyDown event to know which columns were clicked in succession and then use an IComparer
implementation to feed that into.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With