2010-03-17 17 views
5

Tengo un ItemsControl (no virtualizado) que vincula su ItemsSource a una ObeservableCollection de instancias de ViewModel. Ahora, una vez que se carguen las instancias de modelo de gran cantidad, todos los complementos de ViewModel deben agregarse a ese ObservableCollection. ¿Cómo puedo agregar una gran cantidad de ViewModels sin hacer que cuelgue el hilo de la interfaz de usuario?ItemsControl.ItemsSource MVVM performance

Supongo que el subproceso de la interfaz de usuario se cuelga porque cada vez que se agrega un nuevo elemento, ItemsControl necesita actualizarse y hace el diseño, etc. una y otra vez.

  • ¿Debo suspender el enlace agregar todos elementos y luego reanudar? ¿Si es así, cómo?
  • ¿Debo anular el ObservableCollection implementar un AddRange tan sólo el 1 CollectionChanged El evento se activa por la adición de varios artículos ? O, como alternativa, simplemente reemplace toda la colección?
  • ¿O es mejor agregar cada artículo por separado y llamar al Dispatcher.Invocar por cada artículo por separado? Así que desbloquearía con frecuencia.

¿Cómo se manejan las grandes listas dinámicas que no se pueden virtualizar?

+0

¿Qué estás usando? WPF/Silverlight? WinForms? ¿Algo más? – slugster

+0

Debería ser obvio que no se trata de formularios de Windows porque ninguna de las clases mencionadas existe en los formularios de Windows. – bitbonk

+0

¿hay alguna razón específica por la que su control de elementos no pueda usar la virtualización de UI? –

Respuesta

10

Puede crear una clase derivada de una ObservableCollection que le permite suspender temporalmente CollectionChanged eventos como este:

public class SuspendableObservableCollection : ObservableCollection 
{ 
    private bool suspended; 

    public bool Suspended 
    { 
     get 
     { 
      return this.suspended; 
     } 
     set 
     { 
      this.suspended = value; 
      OnCollectionChanged(new NotifyCollectionChangedEventArgs(
       NotifyCollectionChangedAction.Reset)); 
     } 
    } 

    protected override void OnCollectionChanged(
     NotifyCollectionChangedEventArgs args) 
    { 
     if (!Suspended) 
     { 
      base.OnCollectionChanged(args); 
     } 
    } 
} 
+0

Mi pregunta es más acerca de cómo puedo mejorar el rendimiento, no cómo implementar tal colección. Además, si suspendo temporalmente eventos como los que sugiere, ItemsControl mostrará el estado incorrecto después de que se reanude la suspensión. Y si aparece un nuevo evento CollectionChanged, seguirá mostrando el estado incorrecto porque no recibió todas las modificaciones que se hicieron en la colección mientras estaba suspendido. – bitbonk

+0

1) ¿No implementar dicha colección le permite mejorar el rendimiento? 2) Agregué un evento de reinicio para solucionar el problema que describiste. –

+0

Parece que esto no mejora el rendimiento. Probablemente porque tze ItemsControl necesita generar una gran cantidad de controles de elementos a la vez. Así que supongo que el mejor enfoque sería agregar algunos elementos por separado usando (Comenzar) Invocar varias veces. – bitbonk

0
<ItemsControl IsAsync="True" ... /> 
+0

Probablemente quiso decir ''. 'ItemsControl' en sí mismo no tiene esa propiedad. Esta propiedad se debe usar de forma gratuita: "no debe haber muchos escenarios en los que necesite utilizar la propiedad IsAsync. Las directrices .NET recomiendan no definir propiedades que son mucho más lentas de lo que sería un conjunto de campos". – bitbonk

+0

ah, pensé que cada Selector tiene propiedad IsAsync. Cuando carga una ventana que está cargando muchos datos de una manera no asíncrona, obtiene una ventana negra o se cuelga (tal como lo hizo en mi caso con IsAsync = True ahora). ¡Entonces se recomienda usar IsAsync! – Elisabeth

+0

Si está sugiriendo hacer ' 'eso no funciona.' IsAsnyc' solo funciona cuando DataSource en sí no está disponible de inmediato o no toma un tiempo. En mi caso, DataSource está disponible de inmediato, pero solo contiene una gran cantidad de artículos. Lea aquí para obtener más detalles sobre el problema: http://goo.gl/BwA1 – bitbonk