2010-03-17 4 views
5

Ich habe ein (nicht virtualisiertes) ItemsControl, das seine ItemsSource an eine ObeservableCollection von ViewModel-Instanzen bindet. Sobald die große Anzahl von Model-Instanzen geladen ist, müssen alle ViewModel-Komponenten zu dieser ObservableCollection hinzugefügt werden. Wie kann ich eine große Anzahl von ViewModels hinzufügen, ohne dass der UI-Thread hängen bleibt?ItemsControl.ItemsSource MVVM-Leistung

Ich nehme an, der UI-Thread hängt, weil jedes Mal, wenn ein neues Element hinzugefügt wird, das ItemsControl sich selbst aktualisieren muss und Layout usw. immer und immer wieder ausführt.

  • Sollte ich die Bindung aussetzen alle Elemente hinzufügen und dann fortsetzen? Wenn das so ist, wie?
  • Soll ich die ObservableCollection außer Kraft setze eine AddRange so nur 1 Collection Ereignis zu implementieren für Artikel mehr gebrannt Zugabe? Oder alternativ einfach die gesamte Kollektion ersetzen?
  • Oder ist es besser , um jeden Artikel separat hinzuzufügen und Dispatcher.Invoice für jeden Artikel separat anrufen? Also würde ich häufig entsperren.
  • Wie gehen Sie mit großen dynamischen Listen um, die nicht virtualisiert werden können

    +0

    Was verwenden Sie? WPF/Silverlight? WinForms? Etwas anderes? – slugster

    +0

    Es sollte offensichtlich sein, dass es sich nicht um Windows-Formulare handelt, da keine der erwähnten Klassen in Windows-Formularen existieren. – bitbonk

    +0

    Gibt es einen bestimmten Grund, warum Ihr itemscontrol UI Virtualization nicht verwenden kann? –

    Antwort

    10

    Sie können eine von ObservableCollection abgeleitet eine Klasse erstellen, die Sie CollectionChanged Veranstaltungen wie diese vorübergehend zu suspendieren erlaubt:

    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

    Meine Frage geht eher dahin, wie ich die Performance verbessern kann und nicht, wie man eine solche Sammlung implementiert. Auch wenn ich Ereignisse wie Sie vorübergehend aussetze, schlägt das ItemsControl den falschen Zustand vor, nachdem die Aussetzung wieder aufgenommen wurde. Und wenn dann ein neues CollectionChanged-Ereignis ausgelöst wird, zeigt es immer noch den falschen Status an, da es nicht alle Änderungen erhalten hat, die an der Sammlung vorgenommen wurden, während sie angehalten wurde. – bitbonk

    +0

    1) Ermöglicht die Implementierung einer solchen Sammlung nicht die Verbesserung der Leistung? 2) Ich habe ein Reset-Ereignis hinzugefügt, um das beschriebene Problem zu beheben. –

    +0

    Es scheint, dass dies die Leistung nicht verbessert. Wahrscheinlich, weil das ItemsControl viele Item Controls gleichzeitig generieren muss. Ich denke also, der bessere Ansatz wäre, einige Elemente mit (Begin) Invoke mehrmals hinzuzufügen. – bitbonk

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

    Wahrscheinlich meintest du ''. 'ItemsControl' selbst hat diese Eigenschaft nicht. Diese Eigenschaft sollte sparsam verwendet werden: "Es sollte nicht viele Szenarios geben, in denen Sie die IsAsync-Eigenschaft verwenden müssen. Die .NET-Richtlinien empfehlen, Eigenschaften zu definieren, die um Größenordnungen langsamer sind als ein Feldsatz." – bitbonk

    +0

    ah Ich dachte jeder Selector hat IsAsync-Eigenschaft. Wenn Sie ein Fenster laden, das viele Daten auf nicht asynchrone Weise lädt, erhalten Sie ein schwarzes Fenster oder es hängt (in meinem Fall mit IsAsync = True jetzt). Es wird daher empfohlen, IsAsync zu verwenden! – Elisabeth

    +0

    Wenn Sie vorhaben, ' 'zu machen, funktioniert das nicht.' IsAsnyc' funktioniert nur, wenn die DataSource selbst nicht sofort verfügbar ist oder dauert In meinem Fall ist die DataSource sofort verfügbar, enthält aber nur eine große Anzahl von Objekten. Lesen Sie hier mehr über das Problem: http://goo.gl/BwA1 – bitbonk