Basics: ObservableCollection

Wenn Sie ein Abonnement des Magazins 'DATENBANKENTWICKLER' besitzen, können Sie sich anmelden und den kompletten Artikel lesen.
Anderenfalls können Sie das Abonnement hier im Shop erwerben.

Basics: ObservableCollection

Unter WPF gibt es einige Mechanismen, welche die Bindung der Steuerelemente an die zugrunde liegenden Daten in einem gewissen Rahmen automatisieren. Diese werden durch die Programmierung bestimmt – entweder durch die Verwendung bestimmter Schnittstellen für Eigenschaften oder auch durch entsprechende Auflistungstypen, die dann als Datenquelle etwa für Listen-Elemente verwendet werden. Mit der PropertyChanged-Schnittstelle haben wir schon die Synchronisierung zwischen den Attributen der XAML-Definition und Eigenschaften in den Code-Klassen besprochen (siehe Artikel »Basics: PropertyChanged«). In diesem Artikel schauen wir uns nun den Auflistungstyp ObservableCollection an.

Beispielanwendung

Die Beispielanwendung verwendet die auch in den anderen Artikeln genutzte SQLite-Datenbank Bestellverwaltung.db. Wir wollen daraus die Tabelle Kunden nutzen, um die Unterschiede zwischen einer normalen Liste (List) und einer ObservableCollection zu demonstrieren.

Die ObservableCollection-Klasse ist eine Alternative beispielsweise zur List-Klasse. Der wesentliche Unterschied ist, dass die ObservableCollection-Klasse externe Objekte, die den Inhalt einer ObservableCollection anzeigen, über Änderungen informiert.

Änderungen können dabei etwa das Hinzufügen oder Entfernen von Elementen sein. Beispiele für Steuer­elemente, die Sie an Objekte auf Basis der Klasse ObservableCollection binden können, sind etwa das ListBox-Element oder das DataGrid-Element.

Was aber heißt überhaupt »informieren« in diesem Zusammenhang? Wenn Sie etwa unter Access ein Listenfeld an eine Tabelle gebunden und dann einen Datensatz dieser Tabelle gelöscht haben, wurde der Datensatz nach dem Aufruf der Requery-Methode des Listenfeldes auch aus dem Listenfeld entfernt. In einem Formular in der Datenblattansicht führte das Löschen eines Datensatzes direkt zum Entfernen dieses Eintrags aus der Ansicht – sehr praktisch, aber auch logisch, da hier direkt die Tabelle an das Formular gebunden war. Unter WPF ist das alles etwas anders – hier binden Sie ja beispielsweise nicht direkt an Tabellen oder Abfragen, sondern an Auflistungen wie das List-Objekt, Collection oder ObservableCollection, die Sie zuvor noch mit den Daten aus der Datenbank füllen. Wenn Sie nun Änderungen an einem List- oder Collection-Objekt durchführen, wie es etwa geschieht, wenn Sie etwa einen neuen Eintrag hinzufügen oder einen Eintrag löschen, dann wirken sich die Änderungen zwar auf die Einträge des List- oder Collection-Objekts aus, aber sie schlagen sich nicht in der Benutzeroberfläche nieder.

Und hier tritt das ObservableCollection-Objekt auf den Plan: Wenn Sie diesem einen neuen Eintrag hinzufügen oder einen Eintrag entfernen, löst dies ein Ereignis aus, das automatisch von bestimmten Elementen der Benutzeroberfläche wie etwa dem ListBox- oder dem DataGrid-Element implementiert wird und dafür sorgt, dass die Ansicht aktualisiert wird. Um uns dies einmal an einem Beispiel anzusehen, haben wir das Fenster aus Bild 1 erstellt.

Beispiel für an ein List- und ein ObservableCollection-Objekt gebundene DataGrid-Steuerelemente

Bild 1: Beispiel für an ein List- und ein ObservableCollection-Objekt gebundene DataGrid-Steuerelemente

Die Definition dieser Steuer­elemente finden Sie in Listing 1. Das erste DataGrid namens dgList ist an das Objekt KundenList der Code behind-Klasse gebunden, das zweite DataGrid namens dgObservableCollection an das Objekt KundenObservableCollection. Zu jedem DataGrid-Steuerelement haben wir jeweils eine Hinzufügen- und eine Entfernen-Schaltfläche hinzugefügt, mit denen Sie per Code jeweils einen neuen Datensatz anlegen beziehungsweise den aktuell markierten Datensatz aus dem zugrunde liegenden Auflistungsobjekt entfernen. Wir werden dann später erkennen, wo die Unterschiede zwischen dem List- und dem ObservableCollection-Objekt liegen.

<Window x:Class="ObservableCollection.MainWindow" ...  Title="MainWindow" Height="350" Width="525">
     <Grid>
         <Grid.ColumnDefinitions>
             <ColumnDefinition></ColumnDefinition>
             <ColumnDefinition></ColumnDefinition>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="*"></RowDefinition>
             <RowDefinition Height="Auto"></RowDefinition>
         </Grid.RowDefinitions>
         <DataGrid x:Name="dgList" Grid.Column="0" Margin="5" ItemsSource="{Binding KundenList}"></DataGrid>
         <DataGrid x:Name="dgObservableCollection" Margin="5" Grid.Column="1" 
             ItemsSource="{Binding KundenObservableCollection}"></DataGrid>
         <StackPanel Grid.Row="1" Grid.Column="0" Orientation="Horizontal">
             <Button x:Name="btnListAdd" Margin="5" Click="btnListAdd_Click">Add</Button>
             <Button x:Name="btnListDelete" Margin="5" Click="btnListDelete_Click">Delete</Button>
         </StackPanel>
         <StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
             <Button x:Name="btnObservableCollectionAdd" Margin="5" Click="btnObservableCollectionAdd_Click">Add</Button>
             <Button x:Name="btnObservableCollectionDelete" Margin="5" 
                 Click="btnObservableCollectionDelete_Click">Delete</Button>
         </StackPanel>
     </Grid>
</Window>

Listing 1: Definition der beiden DataGrid-Elemente und der Schaltflächen zum Hinzufügen und Löschen der Elemente

DataGrid-Elemente füllen

Damit die beiden DataGrid-Elemente gefüllt werden, haben wir der Code behind-Klasse etwas Code hinzugefügt. Im allgemeinen Teil haben wir dazu zunächst eine Objektvariable für den Datenbankkontext deklariert:

BestellverwaltungEntities dbContext;

Dann benötigen wir ein List-Objekt namens kundenList, das Elemente des Typs Kunde aufnehmen soll und über die öffentliche Eigenschaft KundenList per get und set verfügbar gemacht wird:

private List<Kunde> kundenList;
public List<Kunde> KundenList {
     get {
         return kundenList;
     }
     set {
         kundenList = value;
     }
}

Das Gleiche haben wir für ein Auflistungs-Element des Typs ObservableCollection durchgeführt. Dieses heißt allerdings kundenObservableCollection und wird wie folgt definiert:

Dies war die Leseprobe dieses Artikels.
Melden Sie sich an, um auf den vollständigen Artikel zuzugreifen.

Bitte geben Sie die Zeichenfolge in das nachfolgende Textfeld ein

Die mit einem * markierten Felder sind Pflichtfelder.

Neues aus unseren Magazinen
Listenfeld: Reihenfolge mehrerer Einträge...

Wir haben bereits in mehreren Beiträgen beschrieben, wie Sie die individuelle Reihenfolge von Elementen einer Tabelle über den Inhalt eines Feldes etwa namens »ReihenfolgeID« einstellen können –... [mehr]

Diagramme mit gefilterten Daten

In Ausgabe 2/2019 haben wir in zwei Artikeln die modernen Diagramme von Access vorgestellt. Im vorliegenen Beitrag zeigen wir Ihnen, wie Sie diese abhängig von den in einem Formular angezeigten... [mehr]

Benutzerverwaltung mit verschlüsselten...

Wenn Sie in einer Access-Anwendung Benutzer verwalten wollen, die sich per Benutzername und Kennwort an die Anwendung anmelden, sollten Sie sehr sensibel mit den in der Anwendung gespeicherten... [mehr]

HTML-Tabellen mit fester Kopfzeile

In den vorherigen Ausgaben von Access im Unternehmen und in der aktuellen Ausgabe arbeiten wir in einigen Beiträgen mit dem Webbrowser-Steuerelement und stellen Daten, die wir mit den Bordmitteln... [mehr]

Flexible HTML-Tabellen mit fester Kopfzeile

Im Beitrag »HTML-Tabellen mit fester Kopfzeile« haben wir gezeigt, wie Sie Daten aus einer bestimmten Abfrage in einem Webbrowser-Steuerelement so anzeigen, dass die Spaltenköpfe oben fixiert... [mehr]

Berechtigungen per HTML verwalten

Im Beitrag »Benutzerverwaltung mit verschlüsselten Kennwörtern« stellen wir eine Lösung vor, in der wir die Berechtigungen von Benutzergruppen an Datenbankobjekten definieren. Dort benötigen wir... [mehr]

Benutzer und Berechtigungen ermitteln

In den Beiträgen »Benutzerverwaltung mit verschlüsselten Kennwörtern« und »Berechtigungen per HTML verwalten« haben wir die Voraussetzungen für eine Benutzerverwaltung geschaffen. Im vorliegenden... [mehr]

Zugriffsrechte mit Datenmakros

Es gibt verschiedene Möglichkeiten, auf Basis des aktuell angemeldeten Benutzers sicherzustellen, dass dieser nur die für ihn vorgesehenen Aktionen mit Daten durchführen darf – beispielsweise durch... [mehr]

Kennwörter generieren

Für den einen oder anderen Zweck möchten Sie vielleicht Kennwörter generieren oder in einer Benutzeroberfläche die Möglichkeit zum Generieren von Kennwörtern anbieten. Wenn Sie etwa Benutzer zu... [mehr]

Neuer Datensatz von Frontend zu Backend

Für manche Themen gibt es keine kurze, prägnante Überschrift. In diesem Fall wollen wir zeigen, wie Sie einen neuen Datensatz anlegen, der in einer temporären Tabelle im Frontend gespeichert wird,... [mehr]