2008-10-24 15 views
1

J'ai un ensemble de données dont les éléments sont affichés en tant que lignes dans un DataGrid. L'ordre de tri des lignes change en réponse aux événements externes.Dans Silverlight, comment remplir un DataGrid trié à partir d'une connexion à changement dynamique

Ma pensée initiale était de stocker les lignes en tant que ObservableCollection et de recourir à la collection après les mises à jour. 2) si j'essaie de trier les éléments moi-même, je reçois une exception chaque fois que j'essaye d'assigner un élément à une nouvelle position, par exemple: 1) le ObservableCollection n'a pas de méthode Sort() 2) dans une fonction d'échange comme

class MyCollection : ObservableCollection<T> 
{ 
    void swap(int i, int j) 
    { 
     T tmp = this[i]; 
     this[i] = this[j]; // THROWS A NOT SUPPORTED EXCEPTION 
     this[j] = tmp; 
    } 
} 

la question est ... comment remplir une grille de données dont l'ordre ligne doit mettre à jour dynamiquement?

J'ai finalement obtenu une réponse qui fonctionne, je vais le décrire ci-dessous.

Répondre

1

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.