Das Newport-Framework ist vor nun schon fast vier Jahren beinahe „zufällig“ als Nebenprodukt der ersten App-Entwicklungsexperimente des Autors entstanden. Dieser Artikel zeigt, für welche Einsatzszenarien sich das XAML- und C#-basierende Framework eignet und welche Anwendungsfälle sich damit abdecken lassen.
Als Microsoft 2010 unter der Bezeichnung Windows Phone 7 ein neues mobiles Betriebssystem auf den Markt brachte, erhielten Softwareentwickler die Möglichkeit, ein neues Ökosystem zu erkunden. Wie aber lernt man neue Plattformen, APIs und Entwicklungsparadigmen am besten kennen? Indem man sich an möglichst vielen konkreten Projekten daran versucht. Wie so oft identifiziert der Softwareentwickler in dieser Situation aber schon beim zweiten oder spätestens dritten Projekt gewisse Gemeinsamkeiten und Muster, und eine innere Stimme schreit „Framework, Framework!“.
Nachdem die Forderungen dieser inneren Stimme immer lauter und unüberhörbarer wurden, entwickelte sich parallel zu den Windows-Phone-Apps eine kleine Sammlung von Klassen, Controls und Hilfsroutinen, die in einer Assembly mit dem Namen WP7Utils.dll (Windows Phone 7 Utilities) ihren Platz fanden.
Wie sich allerdings herausstellte, sollte Windows Phone 7 nicht weiterentwickelt, sondern durch Windows Phone 8 abgelöst werden. Zusätzlich erblickte Windows 8 am Desktop-PC mit eigenen Store-Apps das Licht der Welt. Da Windows-8-Store-Apps ähnlich wie Windows-Phone-Silverlight-Apps mit XAML und C# entwickelt werden konnten, lag eine Portierung der WP7Utils auf diese neue Plattform nahe. Diese „Neuportierung“ trug maßgeblich zur neuen Namenswahl bei, und das Entwicklungsframework Newport [1] war geboren.
Nach Microsofts Ankündigung der Universal-Apps auf der hauseigenen Build-Konferenz 2014 wurde das Newport-Framework noch einmal gründlich überarbeitet und ist seitdem in erster Linie für den Applikationstyp der Universal-Apps konzipiert. Silverlight für Windows Phone 7 und Windows Phone 8 werden vom Newport-Framework jedoch weiterhin unterstützt. Newport kann als NuGet-Paket unter [2] bezogen werden, steht aber auch als vollständiges Open-Source-Projekt auf GitHub [3] zur Verfügung. Aktuell kann mit dem Newport-Framework also für folgende Plattformen und Applikationstypen entwickelt werden: Windows Phone 7 Silverlight, Windows Phone 8 Silverlight, Windows-Phone-Universal-Apps, Windows-Store-Universal-Apps.
Newport ist ein Framework, das sich zu 100 Prozent der Applikationsentwicklung unter dem MVVM-(Model-View-ViewModel-)Entwurfsmuster [4] verschrieben hat. Das heißt, es soll Entwickler bestmöglich darin unterstützen, Apps zu programmieren, ohne dabei UI-spezifischen Code oder generell Code-Behind (also Anwendungslogik in GUI-Klassen) schreiben zu müssen. Müsste man die Funktionalität und die Features von Newport kategorisieren, so ließe sich folgende grobe Einteilung treffen:
ViewModels und Commands: Die zentralen Figuren im MVVM-Entwurfsmuster sind ViewModels. Newport bietet neben einigen Basisklassen für ViewModels auch die nötigen Grundbausteine, um ebendiese ViewModels mit den jeweiligen Elementen der Benutzerschnittstelle (den Views) automatisch zu verbinden. Neben den ViewModels selbst zählen Commands und die ICommand-Schnittstelle von .NET zur zweitwichtigsten Säule von MVVM. Erst Commands erlauben die konsequente Trennung von Benutzerschnittstelle und Anwendungslogik, indem sie .NET-Ereignisse in Klassen kapseln, die dann isoliert entwickelt, gewartet und getestet werden können.
Attached Properties und Behaviors: XAML-basierte Applikationen kennen das Konzept von Attached Properties und Behaviors, mit deren Hilfe Funktionalität sozusagen nachträglich einem UI-Element hinzugefügt werden kann. Das ermöglicht eine gute Wiederverwendbarkeit von UI-Code, der ansonsten in Code-Behind-Fragmenten verlorenginge. Die App selbst wird somit von unsauberem, UI-spezifischen Code befreit, und eine neue Eigenschaft steht isoliert als Teil des Frameworks zur Verfügung. Das Newport-Framework macht heftigen Gebrauch von Attached Dependency Properties, um damit Ereignisse (z. B. Touch-Interaktion) über die ICommand-Schnittstelle zur Verfügung zu stellen, womit die zuvor erwähnte Trennung von UI und Anwendungslogik im Sinne des MVVM-Entwurfsmusters ermöglicht wird.
Custom Controls: Die Auswahl der GUI-Controls, die vom Newport-Framework zur Verfügung gestellt werden, folgt keinem bestimmten Muster. Es werden lediglich Controls, die im Zuge der App-Entwicklung entstehen, im Hinblick auf ihre Wiederverwendbarkeit bewertet und im günstigen Fall dem Framework hinzugefügt.
Zusätzlich zu den vorangegangenen Kategorien bietet Newport eine Reihe von Funktionalität an, die in keine definierte Kategorie fällt. Dazu gehören ganz allgemeine Erweiterungsmethoden für .NET-Klassen, Hilfsmittel zur Netzwerkkommunikation wie z. B. eine Implementierung für Simple Service Discovery Protocol SSDP [5] und Abstraktionsmechanismen für Navigation oder zum Persistieren von Applikationseinstellungen.
Werfen wir nun einen Blick auf diese Kategorien und sehen uns anhand von Codebeispielen deren tatsächliche Verwendung an.
Die Schnittstelle INotifyPropertyChanged aus dem System.ComponentModel-Namensraum stellt das Herzstück eines MVVM-Frameworks dar. Erst durch die Implementierung dieser Schnittstelle können Klassen potenziellen Interessenten aktiv Benachrichtigungen über Änderungen an ihren Eigenschaften melden. Die einfachste Form einer ViewModel-Klasse besteht in der Implementierung dieser Schnittstelle, und Newport stellt mit SimpleViewModelBase konsequenterweise eine solche Klasse zur Verfügung. Für einfache Zwecke und Datenmodelle ist eine Ableitung von dieser Klasse vollkommen ausreichend (Listing 1). Die Hilfsmethode SetProperty, die von SimpleViewModelBase bereitgestellt wird, kümmert sich dabei um das Auslösen des PropertyChanged-Ereignisses. Dabei ist zu beachten, dass der eigentliche Name der Eigenschaft (hier Text) nicht zwangsweise spezifiziert werden muss, da er durch das Attribut CallerMemberNameAttribute [6] automatisch zur Verfügung steht. Soll die Applikation jedoch auch Windows Phone 7 unterstützen, steht dieses Attribut bereit, und der Name der Eigenschaft muss explizit angegeben werden. In den meisten Fällen sollte das allerdings kein Thema mehr sein, und dieser Parameter kann getrost weggelassen werden.
Listing 1
public class DemoViewModel : SimpleViewModelBase
{
private string _text;
public string Text
{
get { return _text; }
set { SetProperty(ref _text, value, "Text"); }
}
}
Wer selbst schon Applikationen auf Basis des MVVM-Entwurfsmusters entwickelt hat, dem werden die Zeilen aus Listing 1 höchstwahrscheinlich sehr vertraut vorkommen. Es gibt wohl kaum eine ViewModel-Klasse, die nicht über eine Eigenschaft namens Text oder Name verfügt. Daher stellt Newport mit ViewModelBase eine weitere Basisklasse zur Verfügung, die bereits etwas mehr als nur die reine Implementierun...