XAML-Kolumne: WPF, Silverlight, Windows Phone 8 und Windows-Store-App

WPF-Performancetipp: Gas geben mit der SpeedObservableCollection
Keine Kommentare

In der Kolumne „XAML Expertise“ präsentiert Gregor Biswanger Top-How-tos zum Thema XAML. Einsteiger und fortgeschrittene XAML-Experten sollen hier durch geballtes Wissen gesättigt werden. Heute gibt es folgende Expertise: „WPF-Performancetipp: die SpeedObservableCollection“, „WPF-Performancetipp: ObservableCollection performanter threadübergreifend synchronisieren“ und „XAML: XAML Designer ohne Code laden“.

Unter XAML ist die ObservableCollection enorm wichtig. Jedoch bringt sie bei vielen Datensätzen ein großes Problem mit sich. Sie informiert das UI mit jedem neuen Item auf ein Neues. So wird zum Beispiel bei eintausend Datensätzen auch eintausend Mal das UI informiert, und somit wird jeweils die Oberfläche komplett neu gerendert. Besser wäre es, wenn erst alle Daten in die ObersvableCollection gefüllt werden und erst anschließend das UI davon erfährt.

Die SpeedObservableCollection

Genau das erledigt in diesem Fall die schnell selbst geschriebene Speed ObservableCollection. Diese leitet von der ObservableCollection ab und überschreibt die OnCollectionChanged-Methode. Zusätzlich wird eine weitere Methode mit AddRange hinzugefügt. Dieser kann man ganze Listen übergeben, die erst nach dem vollständigen Hinzufügen der Daten ein CollectionChanged zulässt. Unter Listing 1 steht der Sourcecode zur SpeedObservableCollection.

Ein Test mit einfachen 3 500 Datensätzen zeigt, dass die Standard-ObservableCollection mit ihrem Verhalten zirka eine halbe Sekunde benötigt, um die Daten bei einem DataGrid zu füllen. Mit der SpeedObservableCollection sind die Daten bereits ab zirka zwei Millisekunden auf dem UI. Dieses Beispiel wird unter Abbildung 1 verdeutlicht.

Listing 1: Sourcecode zur „SpeedObservableCollection“

 using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

public class SpeedObservableCollection : ObservableCollection
{
  public SpeedObservableCollection()
  {
    _suspendCollectionChangeNotification = false;
  }

  bool _suspendCollectionChangeNotification;

  protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  {
    if (!_suspendCollectionChangeNotification)
    {
      base.OnCollectionChanged(e);
    }
  }

  public void SuspendCollectionChangeNotification()
  {
    _suspendCollectionChangeNotification = true;
  }

  public void ResumeCollectionChangeNotification()
  {
    _suspendCollectionChangeNotification = false;
  }

  public void AddRange(IEnumerable items)
  {
    SuspendCollectionChangeNotification();

    try
    {
      foreach (var i in items)
      base.InsertItem(Count, i);
    }
    finally
    {
      ResumeCollectionChangeNotification();
      var arg = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset);
      OnCollectionChanged(arg);
    }
  }
}

Abb. 1: „ObservableCollection“ vs. „SpeedObservableCollection“

Abb. 1: „ObservableCollection“ vs. „SpeedObservableCollection“

Aufmacherbild: XAML is presented in the form of binary code  von Shutterstock / Urheberrecht: Profit_Image

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -