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));
I found this article by Dr. WPF which starts out with an answer to my question, then moves on to discuss the performance impact of calling
Refresh. Some key excerpts:He then describes a hacky workaround that improves performance. Rather than calling Refresh, remove, change then re-add the item.
I would have thought it possible that the list view could track an item that changes and know to re-position that item alone within the view.
A new approach was introduced in .NET 3.5 SP1 involving the interface
IEditableObjectthat provides transactional editing via data bindings to the template with methodsBeginEdit(),CancelEdit(), andEndEdit(). Read the article for more information.EDIT As user346528 points out,
IEditableObjectwas not in fact new in 3.5SP1. It actually looks like it’s been in the framework since 1.0.