2009-10-27 12 views
8

Il s'agit de la méthode de tri par défaut lorsque vous cliquez sur un en-tête de colonne dans un DataGrid. Lorsque la liste sous-jacente contient 100 000 éléments, il faut environ 20 secondes pour actualiser la vue. Le même délai peut être observé lors de la configuration SortDescription s sur un CollectionView.Pourquoi trier à l'aide de CollectionViewSource.SortDescriptions est lent?

Le tri en utilisant ListCollectionView.CustomSort ou en triant et en réassociant la liste fonctionne presque instantanément.

Pourquoi ce délai? Est-ce juste une "taxe de réflexion" sur les propriétés liées?

Répondre

9

Vous avez raison, ceci est une taxe de réflexion. J'ai regardé de très près la performance de DataGrid il y a quelque temps, et la réflexion était un goulot d'étranglement ici. Peu importe la rapidité de l'algorithme de tri, ils ne mettent pas en cache la valeur de la propriété entre deux comparaisons. Ainsi, même si vous avez n * ln (n) comparaisons, avec n == 100 000 vous obtiendrez ~ 1 000 000 d'opérations. Chaque opérande utilise la réflexion pour obtenir de la valeur, donc vous avez 2 000 000 d'appels à la réflexion en fiscalité :) ... ListCollectionView.CustomSort est la solution idéale ici.

PS: A la fin de la journée, nous avons écrit la grille à base ListView, parce que nous ne sommes pas satisfaits de la performance DataGrid rendu trop ... Mais c'est une autre histoire :)

1

Le meilleur tweak de performance pour le filtrage, était en train de basculer DataGridRow Visibility. Cela a fait l'ampleur de la différence!

1.Ajoutez la propriété IsVisible à l'élément de collection auquel vous liez la source Item du DataGrid.

private bool _isVisible = true; 
public bool IsVisible 
{ 
    get { return _isVisible; } 
    set 
    { 
     if (_isVisible == value) 
      return; 
     _isVisible = value; 
     RaisePropertyChanged(()=>IsVisible); 
    } 
} 

2.Trigger la visibilité de DataGridRow en se liant à votre IsVisible propriété:

<DataGrid.ItemContainerStyle> 
<Style TargetType="{x:Type DataGridRow}"> 
    <Setter Property="Visibility" 
       Value="{Binding Path=IsVisible, 
           Converter={StaticResource BoolToVisibility}}"/> 
</Style> 
</DataGrid.ItemContainerStyle> 

3.Well, tu dois régler la IsVisible quelque part, je pense aussi, comme dans votre ViewModel. Voici juste un échantillon de ce que je fais (il suffit de copier/coller travail) - mettre essentiellement IsVisible true ou false fonction de certains critères dans mon autre ViewModel:

FilterViewModel.OnFilter += (s, a) => 
{ 
    foreach (Row row in ViewModel.Rows) 
    row.IsVisible = !FilterViewModel.FilteringItems.Any(item => 
            item.IsSelected && item.Name == row.Name); 
}; 
+0

Cela a fonctionné pour moi. C'est ainsi qu'un problème similaire peut être résolu en Angular d'ailleurs :). – Den