Consider this code (type names genericised for the purposes of example):
// Bound to ListBox.ItemsSource
_items = new ObservableCollection<Item>();
// ...Items are added here ...
// Specify custom IComparer for this collection view
_itemsView = CollectionViewSource.GetDefaultView(_items)
((ListCollectionView)_itemsView).CustomSort = new ItemComparer();
When I set CustomSort
, the collection is sorted as I expect.
However I require the data to re-sort itself at runtime in response to the changing of the properties on Item
. The Item
class derives from INotifyPropertyChanged
and I know that the property fires correctly as my data template updates the values on screen, only the sorting logic is not being called.
I have also tried raising INotifyPropertyChanged.PropertyChanged
passing an empty string, to see if a generic notification would cause the sorting to be initiated. No bananas.
EDIT In response to Kent's suggestion I thought I'd point out that sorting the items using this has the same result, namely that the collection sorts once but does not re-sort as the data changes:
_itemsView.SortDescriptions.Add(
new SortDescription("PropertyName", ListSortDirection.Ascending));
With .NET 4.5, WPF added live shaping: https://docs.microsoft.com/en-us/dotnet/framework/wpf/getting-started/whats-new#repositioning-data-as-the-datas-values-change-live-shaping
That allows you to set properties for sorting/grouping/filtering, and if the property value changes, the item is sorted/grouped/filtered again. In your case:
// Bound to ListBox.ItemsSource
_items = new ObservableCollection<Item>();
// ...Items are added here ...
// Add sorting
_itemsView = CollectionViewSource.GetDefaultView(_items)
_itemsView.SortDescriptions.Add(new SortDescription("PropertyName", ListSortDirection.Ascending));
// Enable live sorting
// Note that if you don't add any LiveSortingProperties, it will use SortDescriptions
((ICollectionViewLiveShaping)_itemsView).LiveSortingProperties.Add("PropertyName");
((ICollectionViewLiveShaping)_itemsView).IsLiveSorting = true;
As the accepted answer directs me to, I am able to force single item reposition with code
IEditableCollectionView collectionView = DataGrid.Items;
collectionView.EditItem(changedItem);
collectionView.CommitEdit();
Where changedItem
is the view model (the item in the ItemsSource
collection).
This way you don't need your items to implement any interfaces like IEditableObject
(which in my opinion has very complex and hard to implement contract in some cases).
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