Silverlight und WPF

Schreiben von Silverlight- und WPF-Apps unter Berücksichtigung von Windows-Runtime mit XAML

Pete Brown

 

Windows-Runtime (WinRT) XAML für neue Windows Store-Apps ist das neueste Mitglied der XAML- und C#/Visual Basic-Familie, die viele von uns zu schätzen gelernt haben. All dies begann offiziell 2006 mit Veröffentlichung von Microsoft .NET Framework 3.0 und „Avalon” (später unter dem Namen Windows Presentation Foundation bzw. WPF). Danach folgten zahlreiche weitere Überarbeitungen von WPF, u. a. der neuesten WPF Version 4.5, sowie sieben benannte Silverlight-Versionen (u. a. 1.1 und 5.1), zahlreiche Windows Phone-Versionen usw. Ein Teil des XAML-Stapels ist sogar auf Geräten mit .NET Micro Framework verfügbar.

Sie werden sich möglicherweise fragen, warum es bei XAML und .NET Framework so viele Variationen gibt. Obwohl die Implementierungen bei ähnlichen Verwendungsarten (z. B. Silverlight zum Schreiben von Desktop-Apps) größtenteils zusammengeführt wurden, wurde jede Plattform für unterschiedliche Szenarien und Zielplattformen entwickelt und optimiert. So wurde Silverlight wurde als plattformübergreifendes und webgehostetes Programm entwickelt. XAML für Windows Phone wurde für telefonspezifische Szenarien und Hardware entwickelt, und WinRT XAML für Windows 8 für hoch leistungsfähige, maschinennahe (x86/x64 und ARM), Touch-first (aber nicht Touch-only) Windows Store-Apps.

Dennoch weisen diese XAML-Implementierungen deutlich mehr Gemeinsamkeiten als Unterschiede auf. Genau wegen dieser Gemeinsamkeiten erscheinen diese Unterschiede so ausgeprägt. Aus eigener Erfahrung und aus Gesprächen mit anderen Entwicklern kann ich sagen, dass feinste Unterschiede natürlich viele Herausforderungen für die Entwicklung mit sich bringen können. Jedoch zeigt die Tatsache, dass wir überhaupt so detailliert auf die Kompatibilität eingehen können, die Ähnlichkeit zwischen den Sprachen, Bibliotheken und dem Markup.

Dieser Artikel zeigt zwei wichtige Szenarien: das Freigeben von Code für eine begleitende App und die Zukunftsfähigkeit Ihrer aktuellen Entwicklung.

Begleitende App Dies ist ein Szenario für das gleichzeitige Freigeben von Code bzw. die Cross-Kompilierung für Entwickler von WPF- und Silverlight-Anwendungen, die dabei auch begleitende Windows Store-Apps für Windows 8 erstellen möchten.

Zukunftsfähigkeit In diesem Szenario erstellen Entwickler jetzt neue WPF- und Silverlight-Anwendungen, derzeit aber nicht für Windows 8. Wenn die Organisation Windows 8 einführt, möchten die Entwickler bereit sein; sie möchten die einfachere Portierung entsprechender App-Elemente zur neuen Windows-Benutzeroberfläche gewährleisten.

Aus jahrzehntelanger Programmiererfahrung wissen wir, dass die Wiederverwendung und Portabilität nie einfach so von statten geht. Dennoch werden Sie feststellen, dass der Arbeitsaufwand, der normalerweise mit dem Entwickeln gut strukturierter Apps verbunden ist, mithilfe der hier genannten Techniken nur unwesentlich höher ist.

Eine durchdachte Architektur ist unerlässlich

Die Aufteilung umfangreicher Anwendungen in kleinere Apps ist nur möglich, wenn schon im Vorfeld eine gute Architektur gewährleistet ist. Wenn die Anwendung viele Abhängigkeiten zwischen Codemodulen oder viele große Klassenhierarchien enthält, oder sich der Code als zähe Masse oder unbrauchbar erweist, ist eine Wiederverwendung oder Portierung äußerst schwierig. Aber keine Sorge: Code lässt sich umschreiben, und unter Berücksichtigung der neuen Architektur kann neuer Code geschrieben werden.

Für XAML-Entwickler, die neue Apps erstellen, empfehlen sich folgende grundlegende Ansätze: Bindung, das Model-View-ViewModel (MVVM)-Muster, und Dienstklassen.

Bindung Je mehr die Datenbindung bei der XAML-Entwicklung berücksichtigt wird, desto einfacher ist die Trennung zwischen Logik und Benutzeroberfläche. Im Idealfall wird DataContext für die UI festgelegt und alles weitere von Daten- oder Befehlsbindungen behandelt. In der Praxis können nur wenige Apps diese Stufe der Trennung erreichen, aber je mehr Sie sich dieser annähern, desto einfacher wird es für Sie.

Das MVVM-Muster Das MVVM-Muster geht mit der Datenbindung Hand in Hand. ViewModel ist ein Objekt, an das die Benutzeroberfläche gebunden wird. Da hierzu sehr viele hilfreiche Informationen (und Toolkits, die im weiteren Verlauf genannt werden) kostenlos im Internet und in Büchern zu finden sind, wird an dieser Stelle nicht näher darauf eingegangen.

Dienstklassen Dieser Ansatz ist nicht mit Webdiensten zu verwechseln. Hierbei handelt es sich um Klassen, die dem Client eine wiederverwendbare Funktionalität bereitstellen. In einigen Fällen können sie RESTful oder andere Dienste aufrufen. In anderen Fällen können sie eine Schnittstelle zur Geschäftslogik bieten. In allen Fällen kapseln sie potenziell flüchtigen Code und vereinfachen den Austausch von Implementierungen. In Abbildung 1 spricht ViewModel z. B. Dienstklassen an, um beide Plattformdienste zu nutzen und externe Abhängigkeiten aufzulösen.

Relationship Between the ViewModel and Service Classes
Abbildung 1 Beziehung zwischen ViewModel und Dienstklassen

Ich weiß. Sie denken: „Uh! Noch ein Ebenendiagramm.“ Aber Sie wissen, wie wichtig diese Konzepte sind. Ziel ist, Sie so weit von der Plattform zu entkoppeln, wie Ihr Budget und Ihre Zeit es zulassen. Durch das Ausklammern von Code, der etwa COM- oder P/Invoke-Aufrufe an Desktop-Elemente wie Windows Imaging oder DirectShow sendet, können Sie diese Implementierung einfacher durch die WinRT Kamera-API in der Windows Store-App ersetzen. Dienstklassen sind außerdem optimal geeignet, um andere Plattformunterschiede zu kapseln, z. B. Vertragsimplementierungen: Das Senden einer E-Mail aus einer Windows Store-App erfolgt über einen Vertrag, auf dem Desktop aber wahrscheinlich durch Automatisierung von Outlook oder Verknüpfung mit einem SMTP-Server.

Es ist natürlich leicht, mit der Architektur alle Register zu ziehen und tatsächlich nie etwas bereitzustellen. Eine gute Architektur sollte die Entwicklung vereinfachen, nicht erschweren. Wenn Ihr Team mit jeder Kleinigkeit eines bestimmten Architekturmusters zu kämpfen hat, ist dies möglicherweise vergeudete Zeit. Versuchen Sie stattdessen zu verstehen, wie diese Muster funktionieren und was sie leisten, und treffen Sie dann intelligente und fundierte Entscheidungen über die Kompromisse. In den meisten Fällen ist es besser, eine tolle Architektur zu 85 % zu implementieren, als gar nicht. Die Investitionen, die nötig wären, um die verbleibenden 15 Prozent zu implementieren, lohnen sich zudem oft nicht.

Wenn Sie plattformabhängigen Code ausklammern, lässt sich ein beträchtlicher Teil von anderem nicht trivialem Code wiederverwenden.

Integrieren der Designästhetik der neuen Windows-Benutzeroberfläche

Ziehen Entwickler zunächst das Erstellen von Windows Store-Versionen vorhandener Windows Presentation Foundation (WPF)- und Silverlight-Apps in Betracht, stehen sie direkt vor dem Hindernis, den UX-Entwurf und den visuellen Entwurf überdenken zu müssen. Für die meisten Entwickler ist die Aussicht, eine Anwendung komplett neu gestalten zu müssen, nicht verlockend. Wenn Sie denken, dass Windows Store-Apps auch künftig für Sie ein Thema sind, wird sich die nicht allzu große Arbeit, die sie jetzt in die Berücksichtigung der Designästhetik und -richtlinien der neuen Windows-Benutzeroberfläche investieren, später definitiv auszahlen.

Das Design der neuen Windows-Benutzeroberfläche bietet einen Framework, den Sie bei der Wahl der Benutzeroberfläche-Designmöglichkeiten berücksichtigen können. Für das Windows Store-App-Design gibt es eine große Auswahl an BUILD 2011 Videos. Diese stehen Ihnen auf der MSDN Channel 9-Website unter bit.ly/oB56Vf zur Verfügung. Darüber hinaus gibt es einige Aspekte, die es beim Integrieren der Designästhetik der neuen Windows-Benutzeroberfläche in Desktop-Apps zu beachten gilt:

  • Seien Sie authentisch digital. Allgemein gilt: Vermeiden Sie bei Benutzeroberfläche-Entwürfen die Imitation von physischen Objekten (Skeumorphismus). Sie sollten nicht nur auf die Nachahmung physischer Objekte verzichten, sondern auch auf abgeleitete Techniken wie glänzende Buttons, 3D-Schattierungen, realistische Schatten und Glashintergründe.
  • Verwenden Sie eine klare Typenhierarchie. Verzichten Sie auf eine Fülle von Schriftarten, und konzentrieren Sie sich bei der Auswahl auf einige wenige Größen, die wichtig und leicht zu unterscheiden sind. Überschriften sollten sich klar von Feldbezeichnungen und Hilfetexten abheben.
  • Geben Sie der Anwendung einen Markennamen. Verwenden Sie Farben, Logos, Typ usw. Greifen Sie hierbei auf Webentwickler und -designer zurück, da sie im Bereich Markenbildung oftmals mehr praktische Erfahrung mitbringen.
  • Verwenden Sie eine seitenbasierte Navigationsmetapher. Silverlight-Entwicklern wird dies vertraut sein (der Navigations-Framework ist nahezu identisch), wohingegen der Umstieg vom herkömmlichen Mehrfenster- und Dialog-Desktopsystem für WPF-Entwickler möglicherweise aufwändiger ist.
  • Seien Sie aufgabenorientiert. Konzentrieren Sie sich bei der Benutzeroberfläche auf die jeweiligen Aufgaben, und versuchen Sie nicht, alles in einem einzigen Formular unterzubringen. Leider meinen Benutzer oft, dass sie jede Funktion auf einer einzigen Seite haben möchten, aber mit der Zeit ist dies schwer zu handhaben, zu verwalten und zu erlernen. In manchen Fällen empfiehlt sich die Aufteilung großer Anwendungen in kleinere, aufgabenorientierte Apps.
  • Vermeiden Sie unnötige Verzierungen. Halten Sie die Benutzeroberfläche schlicht. Lenken Sie die Aufmerksamkeit des Benutzers auf das Wesentliche, nicht auf Menüs, Navigationselemente, Fensterrahmen und andere Umrandungen.

Behalten Sie diese Konzepte – ähnlich wie die Designrichtlinien älterer Windows-Benutzeroberflächen – im Hinterkopf. Diese Richtlinien sollten Sie beherzigen, wenn Sie möchten, dass die App dem Benutzer vertraut vorkommt und mit der neuen Windows-Benutzeroberfläche übereinstimmt. Hierzu gibt es natürlich weitere Materialien, daher sollten Sie sich die BUILD-Videos sowie Beispiele von Apps ansehen, die andere Entwickler und Designer geschrieben haben.

Für einen raschen Einstieg in die Benutzeroberflächenformate empfiehlt sich, die Formatressourcen für Windows Store-Apps in die eigenen Desktop-Apps zu kopieren. Viele der Formatressourcen stehen im Windows-Kits-Ordner bereit. Auf meinem Computer befindet sich der Ordner unter C:\Program Files (x86)\Windows Kits\8.0\Include\winrt\xaml\design.

Einige der Formate und Ressourcen können wie vorgesehen verwendet werden. Einige sind wegen neuerer Steuerelemente (z. B. ListView und GridView) nicht brauchbar, und andere bedürfen möglicherweise gewisser Anpassungen. Dennoch bieten sie eine hervorragende Möglichkeit, um der App ein modernes Erscheinungsbild zu verleihen und einen einfachen Übergang zwischen Desktop- und Windows Store-Formaten zu ermöglichen. Selbst wenn sich bestimmte Formate oder Vorlagen nicht direkt verwenden lassen, sind sie lehrreich und ermöglichen einen raschen Einstieg in die eigene Arbeit.

Beim Wechsel zu Windows-Runtime wird die Benutzeroberfläche immer noch einiger Arbeit bedürfen, aber wenn Sie diese Konzepte jetzt in den Apps berücksichtigen, wird dies entscheidend dazu beitragen, dass Benutzer oder Entwickler von den Übergängen zwischen den Apps für die neue Windows Store-Benutzeroberfläche und den Desktop-Apps nicht beeinträchtigt werden.

Machen Sie sich so wenig Arbeit wie möglich. Gestalten Sie die App einmal, vereinfachen Sie den Übergang und erhalten Sie ein modernes Erscheinungsbild als Bonus.

Wiederverwenden von Code und Komponenten

Windows-Runtime wird in neuen Windows Store-Apps viel Aufmerksamkeit gewidmet. Es ist neu, schnell und verfügt über viele tolle Features. Manchmal vergessen wir jedoch, dass Windows-Runtime nicht die Gesamtsumme all dessen ist, woran Sie arbeiten müssen; bei mit XAML erstellten Windows Store-Apps kommt neben Windows-Runtime ein Großteil von .NET Framework 4.5 zum Einsatz. Tatsächlich enthält .NET Framework 4.5 maßgebliche Aktualisierungen, die großteils die gleichzeitige Nutzung mit Windows-Runtime ermöglichen. Es ist jedoch immer noch .NET – das Freigeben von Quellcode oder gar kompilierten Binärdateien für andere .NET-Implementierungen ist durchaus angemessen.

Wenn Sie Code für WPF-Apps freigeben, schreiben Sie den WPF-Code am besten gleich so, dass er mit .NET Framework 4.5 funktioniert. Bei Windows Store-Apps kommt neben Windows-Runtime eine sichere Teilmenge von .NET 4.5 zum Einsatz. Wenn .NET Framework die gleiche Funktionalität bietet wie Windows-Runtime (XAML ist ein sehr gutes Beispiel), verwendet das .NET-Profil für Windows Store-Apps die WinRT-Version. Wenn Sie sich so weit wie möglich an diese Teilmenge halten, wird sich der Code ganz leicht portieren lassen. Das ist besonders hilfreich, wenn Sie mit Diensten und asynchronem Code arbeiten.

Das Freigeben für Silverlight unterliegt insofern gewissen Einschränkungen, als dass Silverlight .NET Framework 4.5 – bzw. meistens auch die Task Parallel Library – nicht verwendet. Mit dem Async Targeting Pack für Silverlight 5 können Benutzer von Visual Studio 2012, die Silverlight-Anwendungen schreiben, jedoch auf einige Task<T>- und async/await-Funktionalitäten zugreifen. Der Code zum Hinzufügen eines Dienstverweises generiert allerdings keinen asynchronen clientseitigen Code. Falls erforderlich, können Sie den generierten Proxycode zu Silverlight portieren. Besser ist es, die Webdienstinteraktionen innerhalb lokaler Dienstklassen anhand der hier vorgesehenen Architektur zu kapseln.

Was geschieht mit identischem Code? Modellklassen – und oft auch ViewModel-Klassen – gehören zu dieser Kategorie. Hier haben Sie zwei Möglichkeiten: PLC (Portable Klassenbibliothek)-Projekte und verknüpfte Projekte.

PCL-Projekte Portable Klassenbibliotheken eignen sich sehr gut, um kompilierte DLLs zwischen verschiedenen .NET-Zielen freizugeben. Sie ermöglichen das Freigeben von Assemblys zwischen .NET, .NET für Windows Store-Apps, Silverlight, Windows Phone usw. Um PLCs verwenden zu können, müssen die Assemblyverweise auf die in der Kompatibilitätsliste enthaltenen Verweise beschränkt werden. Weitere Informationen zu PCLs erhalten Sie unter bit.ly/z2r3eM.

Verknüpfte Projekte mit freigegebenem Quellcode und bedingter Kompilierung Dies ist ein Visual Studio-Feature, das mehrere Projekte ermöglicht, die jeweils auf verschiedene Plattformen abzielen, jedoch über eine einzelne freigegebene Quellcode-Kopie. In der Vergangenheit habe ich diese Methode vor allem beim Freigeben von Code zwischen ASP.NET auf dem Server und Silverlight auf dem Client verwendet. Ein Beispiel hierzu finden Sie in meinem Blog unter bit.ly/RtLhe7

Auch wenn ich für die meisten Wiederverwendungsszenarien in der Regel verknüpfte Projekte verwendet habe, wurden PLCs in den neuen Versionen tatsächlich immer wichtiger. Bei Ausrichtung auf WPF und WinRT XAML kann das .NET 4.5-Profil für Windows Store-Apps mit PLCs fast vollständig verwendet werden. Beginnen Sie im Zweifelsfall mit PLCs.

Einer der Vorteile des Ansatzes über verknüpfte Projekte besteht darin, dass plattformspezifische Zusatzfunktionalitäten über Teilklassen und bedingte Kompilierung bereitgestellt werden können. Symbole für bedingte Kompilierung werden auf der Registerkarte der Projekteigenschaftsseite festgelegt (siehe Abbildung 2.

Project Properties Page Showing Compilation Symbols
Abbildung 2 Projekteigenschaftsseite mit Kompilierungssymbolen

Standardmäßig sind einige Symbole für bedingte Kompilierung definiert (siehe Abbildung 3.

Abbildung 3 Symbole für bedingte Kompilierung

Plattform Kompilierungssymbol
Windows-Runtime + .NET Framework NETFX_CORE
WPF/.NET Framework 4.5-Desktop (Keine)
Silverlight SILVERLIGHT

Bedenken Sie, dass das volle .NET Framework keine Kompilierungssymbole definiert – es gilt als Standardplattform. Wenn Sie sich damit unbehaglich fühlen, können Sie eigene Kompilierungssymbole hinzufügen; stellen Sie nur sicher, dass Sie dabei keines der .NET Framework-Projekte in der Projektmappe vergessen.

Bei der bedingten Kompilierung geht es auch darum, wie sich verschiedene Namespaces im Code, je nach Zielplattform, importieren lassen:

#if NETFX_CORE
using Windows.UI.Xaml;
#else
using System.Windows.Xaml;
#endif

In allen nicht trivialen Apps werden Sie für das Freigeben von Code wahrscheinlich sowohl PLCs als auch verknüpfte Projekte verwenden. Das Freigeben von XAML ist jedoch komplexer.

Freigeben von XAML-Benutzeroberflächen und -Ressourcen

Das Freigeben von XAML ist aus vielen Gründen schwieriger als das Freigeben von Code. Am wichtigsten hierbei ist, die Benutzeroberfläche an die letztendliche Ausführung und Plattform anzupassen. (Siehe „Integrieren der Designästhetik der neuen Windows-Benutzeroberfläche“ für einige der hier genannten Hinweise.) Aus Gründen der Effizienz empfiehlt es sich meistens, Code auf seine Wiederverwendbarkeit zu überprüfen. Dennoch wird XAML tendenziell gerne projektübergreifend freigegeben.

Das Konzept der bedingten Kompilierung ist in XAML nicht vorgesehen. Folglich sind Namespace-Differenzen hier schwieriger handzuhaben als in Code. Neben den Namespaces selbst hat sich auch die Art ihres Imports in XAML zwischen WinRT XAML und anderen Versionen geändert.

Nehmen Sie diese .NET Framework XAML:

xmlns:localControls="clr-namespace:WpfApp.Controls"

Und diese WinRT XAML:

xmlns:localControls="using:WindowsApp.Controls"

Anstelle der „clr-namespace“-Anweisung verwendet WinRT XAML beim Namespace-Import die „using“-Anweisung in XAML. Warum haben sich die Produktteams so entschieden? Importierte Namespaces in XAML stammen möglicherweise z. B. aus Non-CLR-Code – C++. Jetzt wird nicht nur XAML in C++ unterstützt, sondern auch das Schreiben von Assemblys für die Erweiterung in C++ sowie ihre Verwendung im .NET-Code ermöglicht. Das bedeutet, dass der Begriff „clr-namespace“ nicht mehr korrekt ist.

Eine Möglichkeit, den Unterschieden Rechnung zu tragen, ist das dynamische Laden der XAML. In Zeiten von Silverlight 1.1 Alpha wurden auf diese Weise Benutzersteuerelemente generiert: Die XAML wurde zur Laufzeit dynamisch geladen und verarbeitet. Seither wurde diese Methode von App-Entwicklern angewendet, um plattformübergreifende Flexibilität zu gewährleisten.

Beim dynamischen Laden von XAML wird mit Zeichenfolgen gearbeitet. Sie können also Text nach Belieben ersetzen oder Teil eines größeren Texts werden lassen, bevor Sie ihn in die visuelle Struktur laden. Nehmen wir einmal an, ein WPF- oder Silverlight-Projekt enthält die Definition eines leeren Benutzersteuerelements. Das Benutzersteuerelement ist lediglich eine Shell, die die Namespaces und die Klasse definiert. Dann gibt es eine entsprechende Shell im WinRT XAML-Projekt.

Hier ist die .NET XAML:

<UserControl x:Class="WpfApp.Controls.AddressControl"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
  </Grid>
</UserControl>

Und hier ist die WinRT XAML:

<UserControl x:Class="WindowsApp.AddressControl"
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
  <Grid x:Name="LayoutRoot">
  </Grid>
</UserControl>

Bei den beiden XAML-Benutzersteuerelementen handelt es um eine einfache Vorlagenausgabe. Die einzige Änderung besteht darin, dass das Stammraster-Element einen Namen erhalten hat und einige nicht verwendete Namespaces entfernt wurden, um den Code kurz zu halten. Der Codebehind für die Steuerelemente kann mithilfe der Codefreigabeverfahren freigegeben werden, obwohl es sich empfiehlt, den Code nach Möglichkeit in eine separate gemeinsame Klasse zu partitionieren.

Anschließend kann ähnlich wie in Abbildung 4 Code verwendet werden, um die XAML zur Laufzeit zu laden.

Abbildung 4 Code für das dynamische Laden von XAML

public partial class AddressControl : UserControl
{
  public AddressControl()
  {
    InitializeComponent();
    LoadXaml();
  }
  private void LoadXaml()
  {
    string xaml =
    "<Grid xmlns=\"https://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
      "xmlns:x=\"https://schemas.microsoft.com/winfx/2006/xaml\">" +
      "<Grid.RowDefinitions>" +
        "<RowDefinition Height=\"Auto\" />" +
        "<RowDefinition Height=\"30\" />" +
      "</Grid.RowDefinitions>" +
      "<TextBlock Text=\"Address\" Grid.Row=\"0\" FontSize=\"10\" />" +
      "<TextBox x:Name=\"t1\" Grid.Row=\"1\" FontSize=\"15\" />" +
    "</Grid>";
    var reader = new StringReader(xaml);
    var xmlReader = XmlReader.Create(reader);           
    LayoutRoot.Children.Add((UIElement)XamlReader.Load(xmlReader));
  }
}

Der Code zum Laden in WinRT XAML ist wegen der Unterstützung für das direkte Laden von Zeichenfolgen sogar noch einfacher:

string xaml = "..."
LayoutRoot.Children.Add((UIElement)XamlReader.Load(xaml));

Aus Gründen der Einfachheit wurde XAML hier aus einer hartcodierten Zeichenfolge geladen und eine XAML verwendet, die bereits portierbar war und keiner Zeichenfolgenbearbeitung bedurfte. Falls Sie im ersten Fall Designerunterstützung möchten, laden Sie über den Code Text aus einer XAML-Ressourcendatei. Schließen Sie dann alle üblichen Klassen- und xlmns-Definitionen mit ein, um den Designer zu unterstützen, aber verwerfen Sie diese während der XAML-Ladephase.

Ungeachtet dessen, wie die XAML in die visuelle Struktur geladen wird – wenn Sie Ereignisse in die dynamisch geladene XAML einbinden möchten, ist dies ebenfalls über Code möglich:

LayoutRoot.Children.Add((UIElement)XamlReader.Load(xaml));
var t1 = FindName("t1") as TextBox;
if (t1 != null)
{
  t1.TextChanged += t1_TextChanged;
}

Ebenso wie Sie die XAML-Benutzeroberfläche laden können, können Sie Ressourcen zur Laufzeit laden. Sie können diese von Grund auf erstellen oder mithilfe der gleichen hier gezeigten Methoden aus der XAML-Quelle laden:

private void LoadResources()
{
  string xaml =
    "<Style xmlns=\"https://schemas.microsoft.com/winfx/2006/xaml/presentation\" " +
      "TargetType=\"TextBox\">" +
      "<Setter Property=\"Margin\" Value=\"5\" />" +
    "</Style>";
  // Implicit styles use type for key
  var key = typeof(TextBox);
  App.Current.Resources.Add(key, XamlReader.Load(xaml));
}

Wenn Sie Ressourcen dynamisch laden, vergewissern Sie sich, dass sie geladen werden, bevor auf diese verwiesen wird. Im Falle impliziter Formate lassen sich diese auf etwas, das beim Erstellen der Ressource bereits in der visuellen Struktur vorhanden ist, einfach nicht anwenden.

Es soll ganz klar gesagt werden, dass dieser ganze Ansatz ein wenig komplex ist und nicht in jedem Szenario einwandfrei funktioniert. (Ab einem gewissen Punkt bringt die Zeichenfolgenbearbeitung mehr Arbeit als Nutzen) Eine maximale plattformübergreifende Wiederverwendung lässt sich hiermit jedoch erreichen. Für mich persönlich käme diese Option nur für wichtige Benutzeroberflächenkomponenten infrage, die viele Änderungen mit sich bringen oder zu komplex bzw. zu zahlreich sind, um regelmäßig einfach kopiert und eingefügt zu werden.

Sie könnten natürlich auch eine benutzerdefinierte Aktion oder eine andere Visual Studio-Erweiterung schreiben, um die Verarbeitung beim Speichern, Auschecken oder Erstellen von Dateien usw. automatisch zu behandeln.

Die letzte Möglichkeit ist, XAML ganz zu meiden und stattdessen die gesamte Benutzeroberfläche aus Code zu erstellen. Allgemein rate ich bei den meisten Apps davon ab – es bedeutet einen hohen Mehraufwand, und Sie müssen auf Designerunterstützung gänzlich verzichten. Für datengesteuerte Benutzeroberflächen ist dieser Ansatz jedoch bestens geeignet. Wenn Sie diese in XAML erstellen können, funktioniert dies auch in Code (siehe WinRT XAML in Abbildung 5).

Abbildung 5 Erstellen einer Benutzeroberfläche mit WinRT XAML

private void CreateControls()
{
  Grid g = new Grid();
  RowDefinition r1 = new RowDefinition();
  RowDefinition r2 = new RowDefinition();
  r1.Height = new GridLength(1, GridUnitType.Auto);
  r2.Height = new GridLength(30.0);
  g.RowDefinitions.Add(r1);
  g.RowDefinitions.Add(r2);
  TextBlock t = new TextBlock();
  t.Text = "Address";
  Grid.SetRow(t, 0);
  TextBox tb1 = new TextBox();
  Grid.SetRow(tb1, 1);
  g.Children.Add(t);
  g.Children.Add(tb1);
  LayoutRoot.Children.Add(g);
}

Abgesehen von den Schriftarteinstellungen (um es kurz zu fassen) entspricht dieser Code der dynamisch geladenen XAML, die einen TextBlock und TextBox zum LayoutRoot-Raster in einem Raster hinzufügt.

Berücksichtigung von Open Source-Toolkits

Die besten XAML/C#-Toolkits sind großteils Open Source. In einem aktiven Open Source-Projekt werden interessierte Benutzer wahrscheinlich die Arten von Features auswählen und hinzufügen, die den Übergang zwischen Silverlight, WPF und Windows-Runtime ermöglichen.

Es gibt beispielsweise zahlreiche MVVM-Toolkits, die sich weitgehend über verschiedene XAML-Versionen hinweg portieren lassen. Mithilfe eines solchen Toolkits lässt sich die Zahl der Änderungen, die der Quellcode zum Freigeben oder Portieren erfordert, reduzieren. Zudem stehen Ihnen Steuerelemente, lokale Datenbanken und andere Toolkits für eine plattformübergreifende Verwendung zur Verfügung.

Es besteht immer ein Risiko, dass Open Source-Entwickler nicht auf neue Plattformversionen abzielen, aber mit Zugang zum Quellcode könnten Sie den Code aufteilen und bei Bedarf berücksichtigen. Fügen Sie den Code nach Fertigstellung einfach wieder zusammen.

Auswahl der App für die Windows Store-Benutzeroberfläche

Ist es an der Zeit für die Erstellung der neuen Windows Store-App, bedenken Sie, dass sich nicht alle Aspekte sämtlicher Desktop-Anwendungen direkt in Windows Store-Apps übertragen lassen. So gibt eine große Anwendung mit 300 Formularen, die eine gesamte Suite von unterschiedlichen Funktionen für diverse Benutzer ausführt, nicht unbedingt einen guten Kandidaten für die neue Windows-Benutzeroberfläche ab. Stattdessen sollten Windows Store-Apps aufgabenorientiert und auf eine bestimmte Verwendung zugeschnitten sein.

Nehmen Sie z. B. einen Versicherungsantrag. Sie haben eine App, die von vielen Benutzern im Unternehmen benutzt wird. Diese behandelt Aufsichtsfunktionen zum Verwalten der Benutzersicherheit. Sie ermöglicht die Annahme von Glasbruch-Schadenersatzansprüchen per Telefon oder über Laptops im Außendienst. Sie besitzt Funktionen zur Einführung neuer Policen usw.

Wenn Sie die Anwendung in einige kleinere aufgabenorientierte (oder benutzerfokussierte) Apps aufteilen, wird sie für die neue Windows-Benutzeroberfläche besser geeignet sein. Vielleicht möchten Sie eine separate App für Sachverständige im Außendienst, die speziell auf die Erhebung von Informationen am Unfallort ausgerichtet ist. Da sie fokussiert ist, bietet sie Unterstützung für Foto- und Videoaufzeichnungen sowie die Zwischenspeicherung von Daten für Regionen mit fehlender oder unzureichender Verbindung. Möglicherweise nutzt diese App viel Code gemeinsam mit anderen Apps im Unternehmen, aber durch ihren Fokus wird die Anpassung auf die für sie vorgesehenen Szenarien erleichtert.

Zusammenfassung

WinRT XAML, Silverlight und WPF wurden für verschiedenen Zwecke entwickelt, aber dennoch weisen sie mehr Gemeinsamkeiten als Unterschiede auf. Das gemeinsame Nutzen von Code ist einfach, das Freigeben von XAML möglich. Es stehen viele weitere Verfahren zur Verfügung, um alle drei Plattformen einzubeziehen und von der Desktop- zur neuen Windows Store-Benutzeroberfläche überzugehen. Weitere Informationen erhalten Sie bei Twitter oder in meinem Blog unter 10rem.net. Wenn Sie andere Verfahren für das Festlegen von Zielversionen oder Portieren von Code zu Windows-Runtime verwendet haben, würde ich mich freuen, von Ihnen zu hören.

Pete Brown ist Windows 8 XAML- und Gadget-Experte bei Microsoft. Darüber hinaus ist er Autor der Bücher „Silverlight 5 in Action“ (Manning Publications, 2012) und „Windows 8 XAML in Action“ (Manning Publications, 2012). Sie finden seinen Blog und seine Website unter 10rem.net,, oder folgen Sie ihm auf Twitter unter twitter.com/pete_brown.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Tim Heuer