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

Know-how  –  4 Kommentare
Anzeige

Im dritten Teil des Tutorials entstand eine ASP.NET-Weboberfläche für den Webservice zur Flugbuchung. Nun soll eine vergleichbare Windows-Desktop-Anwendung mit WPF geschaffen werden. Dabei kommt das zunehmend beliebtere Pattern Model View ViewModel (MVVM) zum Einsatz.

Die Abbildung 1 zeigt die WPF-Applikation (Windows Presentation Foundation) als Benutzeroberfläche über Webservices, Geschäftslogik und Datenzugriffscode, die in Teil 1 und 2 des Tutorials entstanden sind. Die Anwendung (gelbe Kästen) nimmt die gleiche Position in der Gesamtarchitektur ein und soll die gleichen Funktionen wie die im dritten Teil erstellte Webanwendung erfüllen: Flugauswahl, Passagierauswahl, Flugbuchung und gegebenenfalls das Anlegen eines Passagiers.

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

In den Abbildungen 2 und 3 sieht man das Ergebnis der entwickelten WPF-Anwendung. Wie bei der Webanwendung gibt es zwei Masken: eine für die Buchung und eine für das Erfassen neuer Passagiere. Die Buchungsmaske besteht aus drei Bereichen. Im oberen sucht und wählt man einen Flug, in der Mitte einen Passagier, und unten löst man für den gewählten Flug und Passagier eine Buchung aus. Anders als bei der Webanwendung gibt es aber nur ein Fenster. Die beiden Masken sind fallweise eingeblendete User Controls. Über allem steht ein Ribbon-Steuerelement mit zwei Ribbon Tabs. Das erste Ribbon gehört zur Buchungsmaske, das zweite zur Passagierverwaltung. Mit dem Klick auf das entsprechende Ribbon wird auch der Inhaltsbereich umgeschaltet.

Zweite Ansicht der zu erstellenden WPF-Anwendung (Abb. 3)

Für WPF-Anwendungen gibt es in Visual Studio 2010 für .NET 4.0 drei Projektvorlagen: "WPF Browser Application", "WPF Application" und "WPF Ribbon Application". Die erste Projektart läuft dann allerdings nur im Internet Explorer oder Firefox. Zum Erstellen einer Windows-Desktop-Anwendung wählt man "WPF Application" oder "WPF Ribbon Application". Hier soll Letztere zum Einsatz kommen, in der bereits das Ribbon-Steuerelement angelegt ist.

Das Projekt soll WWWings_WPF heißen. Die WPF-Anwendung benötigt Referenzen auf die in Teil 1 und 2 angelegten Projekte WWWings_GO und WWWings_ServiceProxies sowie die Systembibliothek System.ServiceModel. Außerdem muss der Programmierer die Dienstkonfiguration übernehmen. Dafür kann er die app.config-Datei aus WWWings_TestKonsole im Visual Studio Server Explorer per Drag & Drop nach WWWings_WPF kopieren.

Von der Datenbank bis zur Oberfläche mit .NET

Um das Beispiel mitzuprogrammieren, benötigt der Entwickler Grundkenntnisse in der C#-Syntax und der Handhabung von Visual Studio 2010. Das Tutorial verwendet die englische Version von Visual Studio, weil es in der deutschen Ausgabe einen Fehler gibt, durch den sich das Beispiel nicht ohne viel manuelle Arbeit zum Laufen bringen lässt.

WWWings_WPF erhält durch die Vorlage die Datei MainWindows.xaml mit einem Hauptfenster, das die Grundstruktur eines Ribbons enthält. Das Fenster ist vom vordefinierten Typ RibbonWindow. Das Ribbon wird durch Tags wie Ribbon, RibbonTab, RibbonGroup und RibbonButton strukturiert. Die Oberflächenbeschreibung in WPF erfolgt in XAML (Extensible Application Markup Language), einer von Microsoft geschaffenen XML-Sprache, die wesentlich mächtiger als HTML ist.

Neben der Oberflächenbeschreibung in der XAML-Datei gibt es eine Code-Behind-Datei (.xaml.cs). Das entspricht der Struktur von ASP.NET-Webseiten (.aspx und .aspx.cs, vgl. Teil 3 des Tutorials). Die ebenfalls automatisch angelegte app.xaml-Datei repräsentiert den Einsprungpunkt in die Anwendung; in ihr ist nichts mehr als der Verweis auf MainWindow.xaml enthalten.

Nun gilt es erst mal, die Grundstruktur der WPF-Anwendung anzulegen. Für die beiden User Controls werden ein Ordner "Ansichten" im Projekt und darin zwei Projektelemente vom Typ "User Control (WPF)" mit Namen "BuchungsView" und "NeuerPassagierView" angelegt. Es entstehen jeweils eine .xaml- und eine .xaml.cs-Datei. In die .xaml-Datei kann man für einen ersten Test zwischen die <Grid>-Tags einen Text in der Form <TextBlock>Buchung</TextBlock> beziehungsweise <TextBlock>Neuer Passagier</TextBlock> schreiben. Die Designeroberfläche sollte den Text dann anzeigen.

Zumindest für die beiden User Controls soll die Entwicklung nach dem Model View ViewModell (MVVM) Pattern erfolgen. Darunter versteht man die Adaption des Model View Controller (MVC) Pattern auf WPF und Silverlight. Model und View entsprechen dabei der Bedeutung im klassischen MVC-Entwurfsmuster. Das ViewModel lässt sich als eine spezielle Implementierungsform eines Controllers mit der Aufgabe ansehen, die im Modell enthaltenen Informationen dergestalt aufzubereiten, dass man die Datenbindungstechniken in WPF und Silverlight direkt nutzen kann. Das ViewModel hat außerdem die Aufgabe, sogenannte Commands zu implementieren, die an Ereignisse der Benutzeroberfläche gebunden werden. Das ViewModel kennt die View nicht, und das Model weder das ViewModel noch die View, wie Abbildung 4 veranschaulicht.

MVVM-Entwurfsmuster (Abb. 4)

Das oberste Ziel von MVVM ist es, die Kompetenztrennung, das heißt die Arbeit von Grafikern/Designern (Views erstellen) und die der Entwickler (Model und ViewModel erstellen) zu trennen. Dadurch lässt sich eine Benutzeroberfläche später leicht austauschen. Darüber hinaus sorgt die strikte Trennung für eine Verbesserung der automatisierten Testbarkeit.

Im konkreten Fall heißt das, dass im Ordner "Ansichten" jeweils noch die C#-Klassendateien
BuchungViewModel.cs und NeuerPassagierViewModel.cs anzulegen sind. Beide müssen die Schnittstelle INotifyPropertyChanged implementieren, die dazu dient, die View über Änderungen im ViewModel zu informieren (siehe folgenden Quellcode). Mit konkreten Befehlen in Form von Command Objekten und Properties zur Datenbinding werden diese beiden Klassen erst später gefüllt, denn zunächst soll man nur das Hauptfenster mit der Umschaltung zwischen den beiden Ansichten realisieren. Doch vorab die Grundstruktur des ViewModel für die Buchung-Ansicht:

using System.ComponentModel;
namespace WWWings_WPF.Ansichten
{
public partial class BuchungViewModel : INotifyPropertyChanged
{


/// ########### INotifyPropertyChanged ###########

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}

Gefolgt von der Grundstruktur des ViewModel für die NeuePassagier-Ansicht:

using System.ComponentModel;
namespace WWWings_WPF.Ansichten
{
public partial class NeuerPassagierViewModel : INotifyPropertyChanged
{

/// ########### INotifyPropertyChanged ###########

#region INotifyPropertyChanged Members

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion

}
}
Anzeige