2009-05-12 16 views
22

Estoy trabajando en una aplicación wpf que contiene una vista de lista con un montón de filas de datos (10 000 a 100 000). El usuario puede aplicar todo tipo de filtros a esta vista de lista, haciendo que la lógica del filtro sea bastante avanzada (y lenta). Por ahora, la parte pertinente de mi código es el siguiente:ICollectionView.filter de WPF con grandes conjuntos de datos

ICollectionView view = CollectionViewSource.GetDefaultView(hugeList.ItemsSource); 
view.Filter = new Predicate<object>(FilterCallback); 

private bool FilterCallback(object item) 
{ 
    //Filter logic 
} 

Pero esto se ejecuta en el hilo de interfaz de usuario y bloquea toda la aplicación cuando filtración que da al usuario una experiencia muy pobre. Así que mi pregunta para todos ustedes es: ¿alguien sabe una 'mejor' manera de filtrar una vista de lista en wpf o debería filtrar el subyacente ObservableCollection?

+0

+1 ¡Buena pregunta! ¿Qué solución se te ocurrió? – gehho

+0

Es posible que el problema de rendimiento esté en el aspecto de encuadernación/representación de la cuadrícula y no esté relacionado con la lógica de filtro real ... – Schneider

Respuesta

20

Preste mucha atención a su función de filtro. Asegúrate de que no estés haciendo un boxeo/unboxing innecesario y no estés haciendo cálculos extensos en él. También debe prestar atención a qué tipo de CollectionView está utilizando, algunos son más rápidos que otros. De Bea's post on sorting:

  • Un CollectionView se crea si su fuente implementa IEnumerable. Si la fuente implementa IEnumerable solo, no podrá ordenar o agrupar la colección (solo puede filtrarla). Además, perf no será el mejor si la fuente tiene una gran cantidad de elementos o si realiza operaciones dinámicas como inserciones y eliminaciones. Si este es su escenario, debería considerar que su fuente implemente una interfaz más sólida. ICollection es ligeramente mejor porque proporciona una propiedad Count.

  • ListCollectionView es el tipo de vista creado cuando la fuente implementa IList. Comparado con IEnumerable e ICollection, IList tiene un rendimiento mucho mejor para listas grandes o dinámicas porque proporciona un indexador, lo que nos permite un acceso aleatorio rápido. Además, IList permite ordenar, agrupar y filtrar. Pero, idealmente, su colección de fuentes se deriva de ObservableCollection, la madre de todas las colecciones en términos de enlace de datos, ya que proporciona varios extras adicionales, como notificaciones de cambio de propiedad y de colección.

  • BindingListCollectionView es el tipo de vista creada por Avalon cuando la colección de origen implementa IBindingList. Esta es la vista que tratamos en el escenario ADO.NET. Admite la clasificación y la agrupación, pero no el filtrado tradicional. En su lugar, tiene una propiedad CustomFilter adicional que delega el filtrado a DataView (consulte mi publicación en ADO.NET para obtener más detalles).

Puede patear el filtrado a un subproceso diferente como @mihi dijo pero yo he utilizado CollectionViews ejecutar varios filtros simultáneamente en un ObservableCollection con 50.000 puntos en un objeto con ~ 60 variables (columnas en una tabla de base de datos) sin retraso notable.

Una cosa que noto inmediatamente en su función de filtro es que la entrada es del tipo Objeto, lo que probablemente significa que está haciendo una conversión de tipo dentro de la función y puede que no sea necesario. También utiliza Predicado que no incluye un tipo de devolución, por lo que probablemente requiera algunas conversiones de tipo o reflexión dentro de los métodos de filtrado de CollectionView y también puede ralentizarlo.

+2

¿Podría agregar algún código de muestra para mostrar cómo movería el filtrado a un hilo diferente? Parece que no puedo hacer que esto funcione en un hilo diferente. – Luke

+5

@Bryan: Tengo una situación similar y me gustaría mejorar el rendimiento de mi filtro. Usted escribió en su respuesta que uno debe evitar usar un 'Predicado ' porque requiere operaciones de boxeo/desempaquetado y no incluye un tipo de devolución. ¿Qué quieres decir con eso exactamente? Tiene un tipo de retorno de 'bool', y debe ser un' Predicado 'porque la propiedad' Filter' de 'ListCollectionView' se define así. ¿Hay alguna forma de evitar esto y usar otro enfoque de filtro? ¿O cuál fue tu intención? Tal vez simplemente lo malentendí ... – gehho

+0

@gehho Creo que estaba lanzando ideas en ese momento sobre cosas que podrían estar causando una desaceleración. 99 veces de cada 100 va a ser algo lento en la lógica de filtrado que está causando el problema. –

3

¿Ha considerado filtrar en otro hilo o usar el despachador?

WPF Threads: Build more responsive apps with the dispatcher le ofrece una buena visión general de algunas de las opciones de enhebrado disponibles para usted.

+1

Lo he considerado, pero no puedo acceder al 'ICollectionView' en un hilo diferente al UI hilo? –

+2

No, pero puede realizar la lógica de filtrado en otro hilo y modificar la colección en el hilo de la interfaz de usuario utilizando Dispatcher.Invoke –

+1

Aquí hay un buen ejemplo de esta solución: http://www.codeproject.com/Articles/32426/Deferring- ListCollectionView-filter-updates-for-a –

Cuestiones relacionadas