Я получил это для работы, реализовав INotifyCollectionChanged явно (вместо использования ObservableCollection). Кроме того, я обнаружил, что использование действия «Обновить» привело к той же самой ошибке «не поддерживается», но я мог использовать действия «Добавить» и «Удалить». Так что моя функция подкачки выглядит так:
class MyCollection<T> : List<T>, INotifyCollectionChanged
{
public event NotifyCollectionChangedEventHandler CollectionChanged;
private void swap( int i, int j )
{
T a = this[i];
T b = this[j];
// swap my own internal data storage
this[i] = b;
this[j] = a;
// and also let my CollectionChanged listener know that I have done so.
if( CollectionChanged != null )
{
NotifyCollectionChangedEventArgs arg;
arg = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Remove, a, i );
CollectionChanged( this, arg );
arg = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add, b, i );
CollectionChanged( this, arg );
arg = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Remove, b, j );
CollectionChanged( this, arg );
arg = new NotifyCollectionChangedEventArgs(
NotifyCollectionChangedAction.Add, a, j );
CollectionChanged( this, arg );
}
}
}
Динамические изменения довольно локальны, поэтому, к счастью, использование более медленной рукописной сортировки в ответ на изменения работает хорошо для меня. Другими словами, когда приходят обновления, я вызываю другую функцию-член (из той же коллекции), которая выглядит примерно так:
public void ProcessUpdates( List<T> updateList )
{
// use the contents of updateList to modify my internal store
// ...
// and now resort myself
sort();
}
private void sort()
{
// implement your favorite stable sorting algorithm here, calling
// swap() whenever you swap two elements.
// (this is an intentionally facetious sorting algorithm, because I
// don't want to get into the long and irrelevant details of my own
// data storage.)
while( i_am_not_sorted() )
{
int i = random_index();
int j = random_index();
if( out_of_order(i,j) )
{
// modify my internal data structure and
// also let my CollectionChanged listener know that I have done so
swap( i, j );
}
}
}
Не забывайте, что при добавлении элементов в коллекцию также необходимо запускать уведомление «Добавить»! Я сортирую исходный список, а затем добавляю в отсортированном порядке, что позволяет мне использовать более эффективную библиотеку сортировки при первом заполнении данных.