No Silverlight, como preencher um DataGrid classificado de uma conexão que muda dinamicamente

StackOverflow https://stackoverflow.com/questions/234424

  •  04-07-2019
  •  | 
  •  

Pergunta

Eu tenho um conjunto de dados cujos elementos são exibidos como linhas em um DataGrid. A ordem de classificação para as linhas muda em resposta a eventos externos.

Meu pensamento inicial era armazenar as linhas como um ObservableCollection e recorrer a coleção após atualizações. No entanto eu corri para dois problemas: 1) o ObservableCollection não tem um método de ordenação () 2) se eu tentar classificar os elementos mim, eu recebo uma exceção sempre que eu tentar atribuir um elemento para uma nova posição, por exemplo, em uma função swap como

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

Então a questão é ... como preencher um DataGrid cuja ordem de linha necessidades para atualizar dinamicamente?

Eu finalmente obter uma resposta de trabalho, vou descrevê-lo abaixo.

Foi útil?

Solução

Eu tenho essa para o trabalho através da implementação de INotifyCollectionChanged explicitamente (em vez de usar ObservableCollection). Além disso, descobri que usando a ação de atualização resultou no mesmo "não suportado" erro, mas que eu poderia usar as ações adicionar e remover. Então meus função swap acaba parecendo esta:

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

      }

   }

}

As mudanças dinâmicas são bastante local, por isso, felizmente, usando um tipo mais lento manuscrita em resposta às mudanças está funcionando OK para mim. Em outras palavras, quando as atualizações chegam, invoco outra função de membro (da mesma coleção) que é algo como isto:

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

Não se esqueça que também é necessário para acionar um "Adicionar" notificação ao adicionar elementos para a coleção! Eu meio da lista inicial e, em seguida, adicionar em ordem de classificação, o que me permite usar uma biblioteca mais eficiente tipo quando eu preencher os dados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top