Von der Datenbank bis zur Oberfläche mit .NET, Teil 4: Desktop-Entwicklung mit WPF und MVVM

Seite 4: Eingabemaske

Inhaltsverzeichnis

Nun gilt es noch, die Eingabemaske für neue Passagiere zu gestalten. Wie in der Webmaske gibt es vier Eingabefelder (Vorname, Name, Geburtsdatum und Passagierstatus) und zwei Aktionen (Speichern und Abbrechen), vergleiche Abbildung 2, die hier noch mal gebracht sei.

Erste Ansicht der zu erstellenden WPF-Anwendung (Abb. 2)

Die vier Eingabefelder werden im ViewModel NeuerPassagierViewModel.cs als eine einzige Property (mit INotifyPropertyChanged-Benachrichtigung) vom Typ Passagier erfasst. Die Aktionen sind als Command-Objekte mit der Klasse ActionCommand (siehe Listing 5) realisiert. Zusätzlich ist ein Ereignis NeuerPassagierViewModelExit umgesetzt, das NeuerPassagierViewModel auslöst, wenn entweder nach einem Speichern oder Abbrechen MainWindow die Information erhalten soll, dass wieder auf die Buchungsansicht zurückzuschalten ist. In der Webanwendung übernahm die Funktion Response.Redirect().

Die Speichern()-Routine in NeuerPassagierViewModel hat eine gewisse Ähnlichkeit mit NeuerPassagierManager in der Webanwendung. Allerdings kümmert sich die Speichern()-Routine in NeuerPassagierViewModel selbst um die Konstruktion des Passagier-Objekts aus den Eingabefeldern, denn eine komplett mit der ObjectDataSource aus ASP.NET vergleichbare Funktion gibt es nicht in WPF. Nach der Konstruktion des Objekts erfolgt der Aufruf der Webservice-Operation SavePassagierSet(), aus deren Ergebnis das endgültige Passagier-Objekt inklusive Primärschlüssel ermittelt wird. Bei Erfolg löst das ViewModel das Ereignis NeuerPassagierViewModelExit mit dem neuen Passagier-Objekt als Parameter aus. Bei Misserfolg oder Abbruch ist dieser Parameter null, sodass der Ereignisempfänger erkennen kann, dass kein gültiger neuer Passagier existiert.

Listing 6 zeigt die zugehörige View (NeuerPassagierView.xaml) mit den Datenbindungen für das Passagier-Objekt und zwei Command-Objekten. Die Datenbindungen müssen dabei den Pfad zum "Inneren" des Passagierobjekts beschreiben (z. B. {Binding Passagier.Vorname}), da ja eine Property des Objekts gesetzt werden soll, nicht das Objekt an sich. Die Passagier-Klasse ist eine Entitätsklasse des ADO.NET Entity Framework. Standardmäßig realisieren alle Properties einer Entitätsklasse INotifyPropertyChange, sodass das Zusammenspiel mit WPF gewährleistet ist.

Die Strukturierung des Bildschirms übernimmt auch in NeuerPassagierView ein <Grid>-Element mit sechs gleich hohen Zeilen und zwei Spalten. Innerhalb der Spalte 2 der Zeile 6 ordnet ein <StackPanel> die beiden Befehlsschaltflächen horizontal an.

Wenn der Leser nun die Anwendung startet, wird er feststellen, dass die Passagiereingabemaske zwar die erfassten Passagiere speichert, aber nicht zurück zur Buchungsmaske schaltet. Der Grund dafür liegt darin, dass MainWindowViewModel nicht auf das NeuerPassagierViewModelExit-Ereignis reagiert. Hier ist im Setter der Property Tab2Aktiv die bisherige Zeile

this.ActiveAnsichtViewModel = new 
WWWings_WPF.Ansichten.NeuerPassagierViewModel();

durch folgende Zeilen zu ersetzen:

      //// Später mit NeuePassagierViewModel, der Event auslöst:
var pvm = new WWWings_WPF.Ansichten.NeuerPassagierViewModel();
this.ActiveAnsichtViewModel = pvm;
pvm.NeuerPassagierViewModelExit += delegate(Passagier passagier)
{
Tab1Aktiv = true; // RibbonTab umschalten
this.ActiveAnsichtViewModel =
new WWWings_WPF.Ansichten.BuchungViewModel(passagier);
// ViewModel umschalten und Passagier übergeben
};

Der neue Code bindet das NeuerPassagierViewModelExit-Ereignis an eine zweizeilige Ereignisbehandlungsroutine, die zunächst das RibbonTab wieder und dann das BuchungViewModel unter Übergabe des vom NeuerPassagierViewModelExit-Ereignis gelieferten Passagier-Objekts umschaltet.

Damit das Projekt wieder kompiliert, muss nun der Konstruktor von BuchungViewModel ebenfalls zwei kleine Änderungen erfahren.

  1. Der Konstruktor erhält einen optionalen Parameter für ein Passagier-Objekt: public BuchungViewModel(Passagier passagier = null).
  2. Im Konstruktor ist – insofern ein Passagier-Objekt übergeben wurde – dieses Objekt in die Passagiere-Liste einzuhängen. Außerdem soll das übergebene Objekt das aktuelle Objekt werden. Damit erzielt man den gleichen Effekt wie in der Webanwendung: Ein neu angelegter Passagier erscheint sofort in der Passagierliste und ist auch ausgewählt.
    if (passagier != null)
    {
    Passagiere = new ObservableCollection<WWWings_GO.Passagier>() { passagier };
    Passagier = passagier;
    }

Der Programmcode der Klassen MainWindowViewModel und BuchungViewModel nach diesen Änderungen ist hier nicht mehr wiedergegeben, befindet sich aber im Rahmen der fertigen Gesamtlösung auf dem FTP-Server.

Damit soll die WPF-Anwendung fertig sein. Sicherlich könnte man hie und da die Oberfläche noch verschönern und den Zugriff auf die Webservices durch "Try ... Catch"-Blöcke absichern. Aber auch jetzt ist der Programmcode für eine Tutorialfolge umfangreich geraten.

Dieser Teil des Tutorials hat gezeigt, wie man auf Basis bestehender Webservices eine WPF-Anwendung im modernen Ribbon-Design unter Anwendung des MVVM-Entwurfsmusters realisiert. Auf den ersten Blick besitzt die WPF-Anwendung deutlich mehr Programmcodezeilen als die ASP.NET-Anwendung aus Teil 3. Die Ursache dafür liegt in der aufwendigeren Architektur der Benutzerschnittstelle, präziser gesagt, in der Tatsache, dass zusätzliche Properties und Command-Objekte für die Realisierung des MVVM-Entwurfsmusters zu schreiben waren. Bei Verzicht auf MVVM wären die Menge und der Aufbau des Programmcodes in WPF vergleichbar mit ASP.NET gewesen. Nur dass an die Stelle von HTML und ASP.NET-Steuerelement-Tags in WPF die Oberflächenbeschreibungssprache XAML tritt.

Im fünften und letzten Teil des Tutorials soll erneut XAML zum Einsatz kommen. Die WPF- wird in eine Silverlight-Anwendung umgewandelt, die im Browser läuft. Es wird interessant sein zu sehen, wie viel ein Entwickler dafür an Oberflächenbeschreibung und Benutzerschnittstellensteuerung ändern muss.

Holger Schwichtenberg
leitet das Expertenteam von www.IT-Visions.de, das Beratung und Schulungen im Umfeld von .NET und Microsofts Serverprodukten anbietet. Er hält Vorträge auf Fachkonferenzen und ist Autor zahlreicher Fachbücher.

  • Holger Schwichtenberg; .NET 4.0 Crashkurs; Microsoft Press, 4. Auflage 2010
  • Bernd Marquardt; WPF Crashkurs; Microsoft Press, 2. Auflage 2011