Teil 1: Plattformübergreifende App-Entwicklung mit dem MVVMbasics Framework

Gastbeitrag von Andreas Kuntner

Dieser Artikel ist der erste Teil einer dreiteiligen Serie.

Andreas Kuntner arbeitet als .NET Entwickler mit Schwerpunkt auf Client-, UI- und Mobile Development, und betreut in seiner Freizeit das MVVMbasics Framework und den Developer-Blog https://blog.mobilemotion.eu/

Das Model-View-Viewmodel Design Pattern ist – nicht zuletzt dank Universal Apps für Windows 8 und Windows Phone – mittlerweile den meisten Entwickler ein Begriff. Um das Pattern in „Real Life“ Projekten zu verwenden braucht es aber das eine oder andere MVVM Framework – wer will schon das INotifyPropertyChanged Interface oder Command Binding jedes Mal aufs neue selbst implementieren?

Das MVVMbasics Framework ist seit wenigen Tagen in der Version 2.0 verfügbar – zu diesem Anlass möchte ich euch anhand einer kleinen Demo-App zeigen, was damit möglich ist und wo es die tägliche Arbeit erleichtern kann, sowohl in Bezug auf die typischen MVVM-Anwendungsfälle wie etwas Data und Command Binding, als auch im Bereich der plattformübergreifenden Entwicklung.

Eine erste App

Die komplette Solution steht zum Mitschauen unter https://mobilemotion.eu/downloads/SimpleChat.zip zum Download zur Verfügung – hier im Blog werde ich nur die wichtigsten Code-Snippets zeigen.

Als Demo habe ich einen kleinen, sehr primitiven Chat-Client geschrieben. Dazu ist natürlich eine Server-Anbindung notwendig - Das kann ein Azure-Mobile-Service oder ein beliebiges anderes Webservice sein, ich habe für die Demo ein (sehr reduziertes) Test-Service gebaut dass ich lokal hosten kann, und das nur drei Funktionen bietet: Anlegen eines Users, Senden einer neuen Nachricht, und Abrufen aller neuen Nachrichten. Auf diese drei Funktionen werden wir aus dem Client zugreifen.

Los geht’s! Neue Solution anlegen und ein Projekt hinzufügen – um später für eine plattformübergreifende Lösung gerüstet zu sein, empfehle ich die Models und Viewmodels vom Rest zu trennen. Wir legen also als erstes Projekt eine Portable Class Library an, die .NET 4.5, Windows 8 und Windows Phone 8.1 unterstützt:

44image

 

Zu diesem Projekt muss jetzt die MVVMbasics Bibliothek hinzugefügt werden. Eine Suche nach „mvvmbasics“ im NuGet Package Manager bringt eine Liste an Ergebnissen, wir installieren das erste angebotene Paket „MVVMbasics“ (die weiteren Bibliotheken dienen nur der Abwärtskompatibilität und werden in neuen Projekten nicht mehr benötigt):

45image

 

Jetzt ist es an der Zeit, die Struktur des Programms festzulegen: Für das einfache Demoprogramm ist nur ein einziges Datenmodell nötig das eine einzelne Chatnachricht repräsentiert. Außerdem wird das Programm zwei Pages beinhalten, eines zum Login und eines für den tatsächlichen Chat, für jede dieser Pages brauchen wir ein Viewmodel. (In MVVMbasics existiert immer exakt ein Viewmodel pro Fenster bzw. Page, alle anderen Daten werden in Models organisiert. Diese fixe 1:1-Beziehung ist für die plattformübergreifende Navigation sowie um direkt auf Navigations-Events zu reagieren notwendig, wie wir später noch sehen werden). Wir legen also (zur besseren Übersicht am besten in zwei neuen Namespaces Models und Viewmodels) die Klassen MessageModel, LoginViewmodel und ChatViewmodel an.

Data Binding

Models werden in MVVMbasics immer vom Typ BaseModel abgeleitet, das für eine korrekte (und möglichst einfache) Implementierung des INotifyPropertyChanged Interfaces sorgt. Im Fall des MessageModel erstellen wir drei Properties, die den Namen des Users der die Nachricht geschrieben hat, den Inhalt der Nachricht, und den Zeitpunkt zu dem die Nachricht geschrieben wurde beinhalten. Jedes Property, das an ein Control in der Page gebunden werden soll, muss bei Änderung das PropertyChanged Event auslösen - dafür bietet MVVMbasics die Set Methode:

 private string _username;

public string Username
{
    get { return _username; }
 set { Set(ref _username, value); }
}

Die Set Methode sorgt dafür, dass der Inhalt des Properties mit dem neuen Wert befüllt wird, und löst das PropertyChanged Event aus – beides aber nur dann, wenn der alte und neue Wert des Properties unterschiedlich sind. Die anderen beiden Properties Content und Timestamp werden analog definiert.

Viewmodels müssen immer von der Basisklasse BaseViewmodel abgeleitet werden. Diese erbt intern von BaseModel, sodass die bequeme INotifyPropertyChanged Implementierung wie oben beschrieben auch hier zur Verfügung steht, und bietet zusätzliche Methoden an die für die Navigation gebraucht werden.

Das LoginViewmodel enthält drei Properties: Name und Age (der Benutzer muss zur Anmeldung seinen Namen und sein Alter angeben), sowie Username (dieser setzt sich aus Namen und Alter zusammen und wird zur Anmeldung ans Webservice geschickt). Das Username Property erhält nur einen Setter, der von den anderen beiden Properties abhängt:

 public string Username
{
   get { return String.Format("{0} ({1})", Name, Age); }
}

Name und Age müssen nun zusätzlich zu ihren eigenen auch noch das PropertyChanged Event des Username Properties auslösen. Wir nutzen dazu eine erweiterte Variante der Set Methode:

 private string _name;
public string Name
{
 get { return _name; }
 set { Set(ref _name, value, () => NotifyPropertyChanged(() => Username)); }
}

In diesem Fall wird der Set Methode als dritter Parameter eine Methode (hier in Form einer Lambda Expression) übergeben, die nach dem Aktualisieren des Property-Werts aufgerufen wird, allerdings nur wenn der alte und neue Wert des Properties unterschiedlich waren. Innerhalb dieser Methode lösen wir durch die NotifyPropertyChanged Methode das PropertyChanged Event des Username Property aus.