1

我有一个数据集,其元素在 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?

我终于得到了一个有效的答案,我将在下面描述它。

4

1 回答 1

1

我通过显式实现 INotifyCollectionChanged(而不是使用 ObservableCollection)来实现这一点。此外,我发现使用 Update 操作会导致相同的“不支持”错误,但我可以使用 Add 和 Remove 操作。所以我的交换函数最终看起来像这样:

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

不要忘记,在向集合中添加元素时,还需要触发“添加”通知!我对初始列表进行排序,然后按排序顺序添加,这使我在第一次填充数据时可以使用更有效的库排序。

于 2008-10-24T17:22:21.387 回答