2009-10-27 18 views
8

Este es el método de ordenación predeterminado al hacer clic en el encabezado de una columna en DataGrid. Cuando la lista subyacente contiene 100.000 elementos, se tarda unos 20 segundos en actualizar la vista. Se puede observar la misma demora al establecer SortDescription en un CollectionView.¿Por qué la clasificación con CollectionViewSource.SortDescriptions es lenta?

Ordenando usando ListCollectionView.CustomSort o clasificando y volviendo a asignar la lista funciona casi instantáneamente.

¿Por qué es este retraso? ¿Es esto solo un "impuesto de reflexión" sobre las propiedades vinculadas?

Respuesta

9

Tienes razón, este es un impuesto de reflexión. Miré muy de cerca el rendimiento de DataGrid hace algún tiempo, y la reflexión era un cuello de botella aquí. No importa cuán rápido sea el algoritmo de clasificación, no almacenan en caché el valor de la propiedad entre dos comparaciones. Entonces, incluso si tiene n * ln (n) comparaciones, con n == 100 000 obtendrá ~ 1 000 000 de operaciones. Cada operando utiliza la reflexión para obtener valor, por lo que tiene 2 000 000 llamadas a la reflexión en impuestos :) ... ListCollectionView.CustomSort es la solución ideal aquí.

PD: Al final del día, nos escribió grid de ListView, porque no estábamos satisfechos con el rendimiento del procesamiento DataGrid también ... Pero eso es otra historia :)

1

La mejor ajustar el rendimiento para el filtrado, estaba alternar la visibilidad de DataGridRow. ¡Hizo una gran diferencia!

1.Agregue la propiedad IsVisible al elemento de colección al que vincula el ItemSource de DataGrid.

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

2.Trigger de la visibilidad de DataGridRow mediante la unión a su propiedad IsVisible:

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

3.Well, tienes que establecer el IsVisible algún lugar supongo también, como en el modelo de vista. Esto es sólo una muestra de lo que estoy haciendo (sólo tienes que copiar/pegar trabajo) - básicamente el establecimiento IsVisible a verdadero o falso en base a unos criterios en mi otro modelo de vista:

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

Esto funcionó para mí. Así es como un problema similar puede resolverse en Angular por cierto :). – Den

Cuestiones relacionadas