Reputation: 147290
I have recently stumbled across an issue where the WPF ListView
control seems to be restricting the ability to sort its items. Specifically, I am having a great deal of trouble trying to get a SortDescription
to recognise nested properties (properties of properties).
For straight-forward sorting by propreties, the following line should do the job:
listView.Items.SortDescriptions.Add(new SortDescription("MyProperty",
ListSortDirection.Ascending));
And indeed it works well for me. However, because the ItemSource
for my ListView
is a (strongly-typed) DataTable
, some of the columns are bound to nested properties of the row (i.e. Row.OtherTableRow.SubProperty
binding path style) - it's the way ADO.NET DataSets work for hierarchial databases.
What I would like to do is something like this:
listView.Items.SortDescriptions.Add(new SortDescription("MyProperty.SubProperty",
ListSortDirection.Ascending));
But unfortunately that line throws an ArgumentException
:
'Orders' type does not have property named 'Row.[ID]', so cannot sort data collection.
Strangely enough, I have no problem binding to nested properties. Indeed, the fields display perfectly well in the ListView
... Nor does adding a PropertyGroupDescription
to listView.GroupDescriptions
give me any problems with nested properties - it is only SortDescriptions
!
Is this but a limitation of WPF/the ListView
control? Is there any way I'm going to get support as part of the framework, or will I be out of luck there? If I unfortunately am, and this inconsistency is unavoidable, I would much appreciate if someone could suggest a hack or workaround for this scenario of nested properties. I have tried a few ideas already, but all with minimal success.
Note: I realise that an ORM may well solve my problems, but I'm afraid this isn't at all feasible for the current project I'm working on. Simple ADO.NET DataSets will have to do.
Upvotes: 5
Views: 3760
Reputation: 13008
An alternative to using SortDescription
is to provide an IComparer
object. SortDescription
apparently relies on reflection which may be why nested properties won't work well if at all; but the IComparer
approach has no such limitation, offers much more flexibility, and is claimed to be faster.
The trick in using IComparer
is that ICollectionView
doesn't have the needed .CustomSort
property - however in many (if not all?) cases you can cast the default view to a ListCollectionView
which exposes the required interface.
For instance, I have an ObservableCollection<Something>
whose default view can be cast to ListCollectionView
. I think if this works for ObservableCollection
its probably good for most scenarios.
Here's an example:
ListCollectionView _customerView = CollectionViewSource.GetDefaultView(customers);
as ListCollectionView;
_customerView.CustomSort = new CustomerSorter();
...
public class CustomerSorter : IComparer
{
public int Compare(object x, object y)
{
var custX = (Customer)x;
var custY = (Customer)y;
return custX.Name.CompareTo(custY.Name);
}
}
(Source of slightly modified example: https://wpftutorial.net/DataViews.html#sorting)
Upvotes: 3
Reputation: 426
According to Windows Presentation Foundation Unleased (Adam Nathan), you can cast the default view to a ListCollectionView and set a custom IComparer implementation to its CustomSort property.
Upvotes: 3