Events in der Praxis

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.

Events in der Praxis

Im Artikel »Von VBA zu C#: Objekt-Ereignisse« haben wir bereits die Grundlagen zur Programmierung und Implementierung benutzerdefinierter Ereignisse gelegt. Dies wollen wir nun ausbauen, indem wir uns zwei praktische Beispiele ansehen. Dabei wollen wir von einem Hauptfenster aus verschiedene Ansichten in einem Frame anzeigen, darunter eine Kundenübersicht und eine Kundendetailansicht. Beim Anzeigen sollen verschiedene Dinge geschehen, die wir über die Implementierung von Ereignissen lösen wollen – und zwar über eingebaute sowie über benutzerdefinierte Ereignisse.

Beispielprojekt

Im Beispiel geht es um ein Hauptfenster, das über zwei Ribbon-Buttons verschiedene Page-Elemente in einem Frame anzeigen soll. Die Schaltfläche Kundenübersicht zeigt das Page-Objekt Kundenuebersicht an, die Schaltlfäche Neuer Kunde das Page-Objekt Kundendetails. Diese Seite wird ebenfalls aufgerufen, wenn der Benutzer doppelt auf einen der Einträge der Kundenübersicht klickt (siehe Bild 1).

Interaktion zwischen den einzelnen Seiten

Bild 1: Interaktion zwischen den einzelnen Seiten

Im ersten Beispiel wollen wir dafür sorgen, dass eine dritte Ribbon-Schaltfläche zum Löschen von Elementen der Kundenübersicht nur aktiviert wird, wenn die Kundenübersicht angezeigt wird. Das heißt, dass diese Schaltfläche deaktiviert werden soll, wenn eine andere Ansicht als die Kundenübersicht erscheint. Dazu wollen wir ein Ereignis implementieren, dass beim Seitenwechseln im Frame-Element ausgelöst wird.

Im zweiten Beispiel wollen wir zwei eigene Events programmieren und implementieren. Die Kundenübersicht soll nicht jedes Mal, wenn der Benutzer von einer anderen Seite zurück auf diese Seite wechselt, neu erstellt werden beziehungsweise ihre Daten neu aus der Datenbank einlesen. Dies soll nur geschehen, wenn entweder einer der angezeigten Einträge auf der Seite Kundendetails geändert oder ein neuer Eintrag hinzugefügt wurde. Dazu wollen wir ein Ereignis in der Code behind-Klasse der Seite Kundendetails programmieren, die wir dann in der Code behind-Klasse des MainWindow-Objekts implementieren.

So können wir dann direkt im MainWindow den relevanten Code ausführen und müssen nicht von der untergeordneten Seite mit den Kundendetails auf das übergeordnete Fenster zugreifen – den Hintergrund erläutern wir weiter unten.

Eingebaute Events nutzen

Im ersten Beispiel wollen wir also ein Ribbon-Steuerelement im MainWindow aktivieren oder deaktivieren, je nachdem, welches Page-Element das Frame-Element anzeigt. Wenn es die Seite Kundenuebersicht anzeigt, soll die Schaltfläche btnKundeLoeschen aktiviert werden, wenn es eine andere Seite anzeigt, soll der Benutzer diese Schaltfläche nicht anklicken können.

Dazu legen wir für das Frame-Element im XAML-Code, also in der Klasse MainWindow.xaml, das Attribut Navigated an und füllen es mit dem Wert WorkZone_Navigated:

<Window x:Class="Bestellverwaltung.MainWindow" ...
         Title="MainWindow" Height="450" Width="525">
     <Grid>
         ...
         <Frame x:Name="WorkZone" Grid.Row="1" 
             Navigated="WorkZone_Navigated"></Frame>
     </Grid>
</Window>

Für diese Ereignis hinterlegen wir die folgende Methode in der Code behind-Datei von MainWindow:

private void WorkZone_Navigated(object sender, 
         System.Windows.Navigation.NavigationEventArgs e) {
     switch (WorkZone.Content.ToString()) {
         case "Bestellverwaltung.Kundenuebersicht":
             btnKundeLoeschen.IsEnabled = true;
             break;
         default:
             btnKundeLoeschen.IsEnabled = false;
             break;
     }
}

Diese Methode wird nun beim Wechseln des im Frame-Objekte angezeigten Objekts ausgelöst. Mit einer switch-Bedingung prüfen wir den Namen des angezeigten Elements, hier mit der Eigenschaft Content ermittelt. Hat diese den Wert Bestellverwaltung.Kundenuebersicht, stellt die Methode den Wert der Eigenschaft IsEnabled des Elements btnKundeLoeschen auf true ein. Für jeden anderen Inhalt erhält IsEnabled den Wert false.

Was ist nun der Unterschied zu den Ereignissen etwa einer Schaltfläche, die wir nun schon in vielen Beispielen implementiert haben? In den bisherigen Beispielen haben wir meist selbst die Ereignisse ausgelöst, zum Beispiel durch einen Mausklick auf eine Schaltfläche. Diesmal wurde das Ereignis indirekt durch unsere Aktion ausgelöst, nämlich durch einen Klick auf eine Ribbon-Schaltfläche, die wiederum den Inhalt des Frame-Objekts geändert hat. Und das hat dann unser hier implementiertes Ereignis hervorgerufen.

Benutzerdefinierte Events

Wie oben gezeigt, gibt es eine große Anzahl eingebauter Ereignisse, die Sie für Ihre Zwecke nutzen können. Nicht immer jedoch werden Ereignisse zum gewünschten Zeitpunkt ausgelöst. Ein Beispiel ist das Speichern eines Kunden, der neu angelegt oder geändert wurde. Unter Access, wo alles auf die Anzeige und Bearbeitung von Daten ausgelegt ist, finden Sie entsprechende Ereignisse zuhauf – zum Beispiel das Ereignis Nach Aktualisierung. Unter WPF/C# sorgen wir selbst dafür, dass die Änderungen an den angezeigten Daten auch in die Datenbank geschrieben werden. Dementsprechend müssen wir auch selbst Ereignisse definieren, die zu einem solchen Zeitpunkt ausgelöst werden.

In unserem Fall wollen wir ein solches Ereignis nutzen, um festzulegen, ob eine Änderung oder eine Neuanlage eines Kunden erfolgt ist. Abhängig davon soll die Kundenübersicht, wenn sie das nächste Mal eingeblendet wird, entweder neu erzeugt werden (falls Änderungen vorliegen) oder mit den alten Daten eingeblendet werden.

Dazu soll das Hauptfenster eine Variable namens KundenChanged vorhalten, die lesend und schreibend zugreibar ist und wie folgt in der Klasse MainWindow deklariert wird:

public bool KundeChanged { get; set; }

Die einfache Variante

Nun könnten wir im Page-Objekt Kundendetails die Schaltfläche Speichern mit einer Anweisung ausstatten, welche die Eigenschaft KundeChanged einfach auf den Wert true einstellt, wenn der Benutzer die Schaltfläche betätigt hat (siehe Bild 2).

Ein Klick auf Speichern stellt die Eigenschaft KundeChanged im MainWindow auf true ein.

Bild 2: Ein Klick auf Speichern stellt die Eigenschaft KundeChanged im MainWindow auf true ein.

In diesem einfachen Fall sieht die Methode, die beim Anklicken der Speichern-Schaltfläche ausgelöst wird, wie in Listing 1 aus. Die erste Anweisung prüft, ob es sich um einen neuen Kunden handelt (in diesem Fall ist die ID noch 0, da noch nicht vom Datenbanksystem vergeben). Ist der Kunde neu, wird er im ersten Teil der If-Bedingung hinzugefügt und in der Datenbank gespeichert. Außerdem referenzieren wir das MainWindow-Objekt über Window.GetWindow(this) und stellen anschließend seine Eigenschaft KundeChanged, die wir weiter oben als öffentliche Variable des Fensters MainWindow deklariert haben, auf den Wert True ein. Handelt es sich um einen vorhandenen Kunden, der geändert wurde, speichern wir ebenfalls die Änderungen in der Datenbank und stellen dann wir oben den Wert der Eigenschaft KundeChanged auf True ein.

private void btnSpeichern_Click(object sender, RoutedEventArgs e) {
     bool kundeCreated = kundeTemp.ID == 0;
     if (kundeCreated) {
         dbContext.Kunden.Add(kundeTemp);
         dbContext.SaveChanges();
         MainWindow wnd = 
             (MainWindow)Window.GetWindow(this);
         wnd.KundeChanged = true;
     }
     else {
         dbContext.SaveChanges();
         MainWindow wnd = 
             (MainWindow)Window.GetWindow(this);
         wnd.KundeChanged = true;
     }
}

Listing 1: Beispiel für das Aktualisieren einer Variablen durch direkten Zugriff

Neuerstellen oder nicht?

Wenn der Benutzer nun im MainWindow auf die Ribbon-Schaltfläche btnKunden­uebersicht klickt, löst er die Ereignismethode btnKundenuebersicht_Click aus Listing 2 aus. Diese prüft im ersten Teil der if-Bedingung vor dem Oder-Zeichen (|), ob kundenuebersicht überhaupt schon existiert, also nicht den Wert null enthält – in diesem Fall wird dieses Page-Objekt auf jeden Fall neu erstellt. Der Teil hinter dem Oder-Zeichen prüft, ob die Boolean-Variable KundeChanged den Wert true enthält.

private void btnKundenuebersicht_Click(object sender, RoutedEventArgs e) {
     if (kundenuebersicht == null | KundeChanged == true) {

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.

Ich habe die Datenschutzbestimmungen zur Kenntnis genommen.