В Silverlight, как заполнить отсортированный DataGrid из динамически меняющегося соединения - PullRequest
1 голос
/ 24 октября 2008

У меня есть набор данных, элементы которого отображаются в виде строк в DataGrid. Порядок сортировки строк изменяется в ответ на внешние события.

Сначала я думал сохранить строки как ObservableCollection и обработать коллекцию после обновлений. Однако я столкнулся с двумя проблемами: 1) ObservableCollection не имеет метода Sort () 2) если я пытаюсь отсортировать элементы самостоятельно, я получаю исключение, когда пытаюсь присвоить элемент новой позиции, например, в функции подкачки, такой как

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;
   }
}

Итак, вопрос в том ... как заполнить DataGrid, порядок строк в котором нужно динамически обновлять?

Я наконец-то получил один ответ, я опишу его ниже.

1 Ответ

1 голос
/ 24 октября 2008

Я получил это для работы, реализовав 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 );
       }
    }
}

Не забывайте, что при добавлении элементов в коллекцию также необходимо запускать уведомление «Добавить»! Я сортирую исходный список, а затем добавляю в отсортированном порядке, что позволяет мне использовать более эффективную библиотеку сортировки при первом заполнении данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...