J'ai obtenu ceci pour travailler en implémentant explicitement INotifyCollectionChanged (au lieu d'utiliser ObservableCollection). De plus, j'ai trouvé que l'utilisation de l'action Mettre à jour entraînait la même erreur "non supporté", mais que je pouvais utiliser les actions Ajouter et Supprimer. Donc, ma fonction d'échange finit par ressembler à ceci:
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);
}
}
}
Les changements dynamiques sont assez local, en utilisant si heureusement une sorte manuscrite plus lent en réponse aux changements qui fonctionne bien pour moi. En d'autres termes, lorsque les mises à jour arrivent, j'invoque une autre fonction membre (dans la même collection) qui ressemble à quelque chose comme ceci:
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);
}
}
}
Ne pas oublier qu'il est aussi nécessaire de tirer une notification « Ajouter » lors de l'ajout d'éléments à la collection! Je trier la liste initiale et ensuite ajouter dans l'ordre trié, ce qui me permet d'utiliser un tri de bibliothèque plus efficace lorsque je peuple d'abord les données.