Sonderausgabe 2015 zu Windows 10

Band 30, Nummer 11

Entwurf von Benutzeroberflächen – Adaptive Apps für Windows 10

Von Clint Rutkas | Windows 2015

Dank der universellen Windows-Plattform (UWP) unter Windows 10 können Anwendungen nun auf einer Vielzahl von Gerätefamilien ausgeführt und für die verschiedenen Bildschirm- und Fenstergrößen skaliert werden, die von den Plattformsteuerelementen unterstützt werden. Wie unterstützen diese Gerätefamilien die Benutzerinteraktion mit Ihren Apps, und wie reagieren Ihre Apps auf das Gerät, auf dem sie ausgeführt werden, bzw. wie passen sie sich an? Wir erörtern dies und die Tools und Ressourcen, die Microsoft auf der Plattform bietet, damit Sie nicht komplexen Code für Apps schreiben und verwalten müssen, die auf verschiedenen Gerätetypen ausgeführt werden.

Lassen Sie uns mit den Reaktionstechniken beginnen, mit deren Hilfe Sie die Benutzeroberfläche für verschiedene Gerätefamilien optimieren können. Anschließend gehen wir eingehender darauf ein, wie sich Ihre App an bestimmte Gerätefunktionen anpassen kann.

Ehe wir uns näher mit Steuerelementen, APIs und Code beschäftigen, wollen wir zunächst die Gerätefamilien vorstellen, von denen die Rede ist. Einfach ausgedrückt: Eine Gerätefamilie umfasst Geräte mit einem bestimmten Formfaktor, die von IoT-Geräten, Smartphones, Tablets und Desktop-PCs zu Xbox-Spielkonsolen, Surface Hub-Großbildschirmgeräten und tragbaren Geräten reichen können. Apps funktionieren auf allen diesen Gerätefamilien, doch Sie sollten beim Entwickeln Ihrer Apps unbedingt die Gerätefamilien berücksichtigen, auf denen diese genutzt werden könnten.

Wenngleich es zahlreiche Gerätefamilien gibt, ist die UWP so ausgelegt, dass 85 % ihrer APIs allen Apps unabhängig vom Gerät zur Verfügung stehen, auf dem sie ausgeführt werden. Zudem ergibt sich bei einer Untersuchung der 1.000 beliebtesten Apps, dass 96,2 % aller verwendeten APIs vom standardmäßigen universellen Windows-API-Satz abgedeckt sind. Der Großteil der Funktionalität ist als Teil der UWP vorhanden und verfügbar, wobei spezialisierte APIs für jedes Gerät zur Verfügung stehen, um Ihre App weiter anzupassen.

Willkommen zurück, Fenster

Eine der größten Änderungen bei der Nutzung von Apps unter Windows ist etwas, womit Sie bereits umfassend vertraut sind: die Ausführung von Apps in einem Fenster. Windows 8 und Windows 8.1 ermöglichen Apps die Ausführung im Vollbild bzw. maximal vier Apps die gleichzeitige Ausführung nebeneinander. Windows 10 ermöglicht dagegen dem Benutzer, Apps in der gewünschten Größe anzuordnen bzw. zu positionieren. Der neue Ansatz unter Windows 10 bietet dem Benutzer mehr Flexibilität, was die UI angeht, erfordert aber ggf. etwas mehr Aufwand auf Ihrer Seite für die entsprechenden Optimierungen. Die Verbesserungen in XAML unter Windows 10 ermöglichen eine Vielzahl von Möglichkeiten zum Implementieren reaktionsfähiger Techniken in Ihre App, damit sie unabhängig von Bildschirm- oder Fenstergröße ansprechend aussieht. Sehen wir diese drei Ansätze einmal genauer an.

VisualStateManager Unter Windows 10 wurde die "VisualStateManager"-Klasse um zwei Mechanismen zum Implementieren des reaktionsfähigen Designs in Ihre XAML-basierten Apps erweitert. Die neuen APIs "VisualState.StateTriggers" und "VisualState.Setters" erlauben Ihnen das Definieren visueller Zustände, die bestimmten Bedingungen entsprechen. Visuelle Zustände können sich basierend auf der Höhe und Breite des App-Fensters ändern, indem der integrierte "AdaptiveTrigger" als "StateTrigger" von "VisualState" verwendet wird und die Eigenschaften "MinWindowHeight" und "MinWindowWidth" verwendet werden. Sie können auch "Windows.UI.Xaml.State­­TriggerBase" erweitern, um eigene Trigger z. B. für das Auslösen von Instanzen gemäß der Gerätefamilie oder des Eingabetyps zu erstellen. Betrachten Sie den Code in Abbildung 1.

Abbildung 1: Erstellen benutzerdefinierter Zustandstrigger

<Page>
  <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup>
        <VisualState>
          <VisualState.StateTriggers>
          <!-- VisualState to be triggered when window
            width is >=720 effective pixels. -->
            <AdaptiveTrigger MinWindowWidth="720" />
          </VisualState.StateTriggers>
          <VisualState.Setters>
            <Setter Target="myPanel.Orientation"
                    Value="Horizontal" />
          </VisualState.Setters>
        </VisualState>
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <StackPanel x:Name="myPanel" Orientation="Vertical">
      <TextBlock Text="This is a block of text. It is text block 1. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
      <TextBlock Text="This is a block of text. It is text block 2. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
      <TextBlock Text="This is a block of text. It is text block 3. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
    </StackPanel>
  </Grid>
</Page>

Im Beispiel in Abbildung 1 zeigt die Seite drei "TextBlock"-Elemente, die im Standardzustand übereinander gestapelt sind. "VisualStateManager" hat einen "AdaptiveTrigger", der mit dem "MinWindow­Width"-Wert 720 definiert ist. Dieser bewirkt, dass die Ausrichtung von "StackPanel" sich in "Horizontal" ändert, wenn das Fenster mindestens 720 effektive Pixel breit ist. Dadurch können Sie den zusätzlichen horizontalen Bildschirmplatz nutzen, wenn Benutzer die Fenstergröße ändern, oder auf einem Smartphone oder Tablet vom Hochformat zum Querformat wechseln. Beachten Sie, dass wenn Sie die Eigenschaften "Width" und "Height" definieren, Ihr Trigger nur einmal ausgelöst wird, sollte die App beide Bedingungen gleichzeitig erfüllen. Sie können das Beispiel mit den "State"-Triggern auf GitHub (wndw.ms/XUneob) untersuchen, um mehr Szenarien kennenzulernen, in denen Trigger verwendet werden, einschließlich verschiedener benutzerdefinierter Trigger.

RelativePanel Im Beispiel in Abbildung 1 wird ein "StateTrigger" verwendet, um die "Orientation"-Eigenschaft von "StackPanel" zu ändern. Die vielen Containerelemente in XAML ermöglichen Ihnen in Kombination mit "State"-Triggern die Änderung Ihrer Benutzeroberfläche auf vielfältige Weise. Sie bieten aber keine Möglichkeit zum Erstellen einer komplexen, reaktionsfähigen UI, auf der Elemente in Bezug zueinander angeordnet sind. Hier kommt das neue "RelativePanel" ins Spiel. Wie in Abbildung 2 gezeigt, können Sie ein "RelativePanel" für das Layout Ihrer Elemente verwenden, indem Sie räumliche Beziehungen zwischen Elementen ausdrücken. Dies bedeutet, dass Sie "RelativePanel" zusammen mit "AdaptiveTriggers" zum Erstellen einer reaktionsfähigen UI nutzen können, bei der Sie Elemente basierend auf dem verfügbaren Bildschirmplatz verschieben.

Abbildung 2: Ausdrücken räumlicher Beziehungen mit "RelativePanel"

<RelativePanel BorderBrush="Gray" BorderThickness="10">
  <Rectangle x:Name="RedRect" Fill="Red" MinHeight="100" MinWidth="100"/>
  <Rectangle x:Name="BlueRect" Fill="Blue" MinHeight="100" MinWidth="100"
             RelativePanel.RightOf="RedRect" />
  <!-- Width is not set on the green and yellow rectangles.
       It's determined by the RelativePanel properties. -->
  <Rectangle x:Name="GreenRect" Fill="Green"
             MinHeight="100" Margin="0,5,0,0"
             RelativePanel.Below="RedRect"
             RelativePanel.AlignLeftWith="RedRect"
             RelativePanel.AlignRightWith="BlueRect"/>
  <Rectangle Fill="Yellow" MinHeight="100"
             RelativePanel.Below="GreenRect"
             RelativePanel.AlignLeftWith="BlueRect"
             RelativePanel.AlignRightWithPanel="True"/>
</RelativePanel>

Zur Erinnerung: Die Syntax, die Sie mit angefügten Eigenschaften verwenden, umfasst zusätzliche Klammern (siehe folgenden Code):

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState>
      <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowWidth="720" />
      </VisualState.StateTriggers>
      <VisualState.Setters>
        <Setter Target="GreenRect.(RelativePanel.RightOf)"
                Value="BlueRect" />
      </VisualState.Setters>
    </VisualState>

Auf GitHub finden Sie unter "Responsiveness techniques sample" (wndw.ms/cbdL0q) weitere Szenarien, bei denen "RelativePanel" zum Einsatz kommt.

SplitView Die App-Fenstergröße wirkt sich auf mehr aus als auf den auf den App-Seiten angezeigten Inhalt. Sie kann erforderlich machen, dass Navigationselemente auf Änderungen der Größe des Fensters selbst reagieren. Das in Windows 10 eingeführte neue "SplitView"-Steuerelement wird zumeist zum Erzeugen einer Navigationsumgebung auf oberster Ebene genutzt, die so angepasst werden kann, dass sie sich je nach Größe des App-Fensters anders verhält. Auch wenn dies einer der gängigsten Anwendungsfälle für "SplitView" ist, bleibt dieses Steuerelement nicht auf diesen Zweck begrenzt. "SplitView" ist in zwei gesonderte Bereiche unterteilt: Bereich und Inhalt.

Die Darstellung kann mithilfe verschiedener Eigenschaften für das Steuerelement geändert werden. Zuerst gibt "DisplayMode", wie der Bereich in Bezug auf den Abschnitt "Content" gerendert wird. Es gibt vier Modi: Overlay, Inline, CompactOverlay und CompactInline. Abbildung 3 zeigt Beispiele der in einer App gerenderten Modi "Inline", "Overlay" und "CompactInline".

"DisplayMode"-Navigationselemente
Abbildung 3: "DisplayMode"-Navigationselemente

Die "PanePlacement"-Eigenschaft zeigt den Bereich entweder links (Standard) oder rechts neben dem Abschnitt "Content" an. Die "OpenPaneLength"-Eigenschaft gibt die Breite des Bereichs an, wenn dieser vollständig erweitert ist (standardmäßig 320 effektive Pixel).

Beachten Sie, dass das "SplitView"-Steuerelement kein integriertes UI-Element für Benutzer zum Umschalten des Zustands des Bereichs bietet, vergleichbar mit dem gängigen "Hamburger"-Menü, das in mobilen Apps häufig zu finden ist. Wenn Sie dieses Verhalten ermöglichen möchten, müssen Sie das UI-Element in Ihrer App definieren und Code zum Umschalten der "IsPaneOpen"-Eigenschaft von "SplitView" angeben.

Möchten Sie die gesamte Palette von Features kennenlernen, die das "SplitView"-Steuerelement zu bieten hat? Sehen Sie sich hierzu auf GitHub (wndw.ms/qAUVr9) das "Navigation menu (XAML) sample" an.

Hinzufügen der Schaltfläche "Zurück"

Wenn Sie Apps für frühere Versionen von Windows Phone entwickelt haben, sind Sie ggf. daran gewöhnt, dass jedes Gerät eine hardware- oder softwaregestützte Schaltfläche "Zurück" hat, die Benutzern die Rückwärtsnavigation durch Ihre App ermöglicht. Für Windows 8 und 8.1 mussten Sie jedoch Ihre eigene UI für die Rückwärtsnavigation erzeugen. Um Ihnen das Leben leichter zu machen, wenn es als Ziele mehrere Gerätefamilien in Ihrer Windows 10-App gibt, bieten wir eine Möglichkeit zum Sicherstellen eines einheitlichen Rückwärtsnavigationsmechanismus für alle Benutzer. Dieser kann Ihnen bei Ihren künftigen Apps helfen, etwas UI-Platz freizugeben.

Zum Ermöglichen einer Systemschaltfläche "Zurück", auch auf Gerätefamilien ohne hardware- oder softwaregestützte Schaltfläche "Zurück" (wie z. B. Laptops oder Desktop-PCs), verwenden Sie die "AppViewBackButtonVisibility"-Eigenschaft in der "SystemNavigationManager"-Klasse. Rufen Sie einfach die "SystemNavigationManager"-Klasse für die aktuelle Ansicht ab, und legen Sie die Sichtbarkeit der Schaltfläche "Zurück" fest (siehe den folgenden Code):

SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
  AppViewBackButtonVisibility.Visible;

Die "SystemNavigationManager"-Klasse macht auch ein "BackRequested"-Ereignis verfügbar, das ausgelöst wird, wenn der Benutzer die vom System bereitgestellte Schaltfläche, Geste oder einen Sprachbefehl für die Rückwärtsnavigation aufruft. Dies bedeutet, dass Sie dieses einzelne Ereignis so verarbeiten können, dass die Rückwärtsnavigation in Ihrer App bei allen Gerätefamilien einheitlich erfolgt.

Vorteile von Continuum

Zu guter Letzt möchten wir einen unserer persönlichen Favoriten vorstellen: Continuum unter Windows 10. Mithilfe von Continuum passt Windows 10 Ihre Erfahrung dahingehend an, was Sie tun möchten und wie Sie es tun möchten. Wenn Ihre App beispielsweise auf einem 2-in-1-Windows-PC läuft, ermöglicht die Implementierung von Continuum in Ihrer App Benutzern das Verwenden der Touch- oder Maus- und Tastatureingabe zum Optimieren der Produktivität. Mithilfe der "UserInteractionMode"-Eigenschaft in der "UIViewSettings-Klasse kann Ihre App bestimmen, ob der Benutzer mit der Ansicht mittels Touch- oder Maus- und Tastatureingabe interagiert, und zwar mit nur einer Codezeile:

UIViewSettings.GetForCurrentView().UserInteractionMode;
// Returns UserInteractionMode.Mouse or UserInteractionMode.Touch

Nach Erkennen des Interaktionsmodus können Sie die UI Ihrer App optimieren, indem Sie z. B. Ränder vergrößern oder verkleinern, komplexe Features ein- oder ausblenden usw. Lesen Sie den TechNet Wiki-Artikel "Windows 10 Apps: Leverage Continuum Feature to Change UI for Mouse/Keyboard Users Using Custom StateTrigger" von Lee McPherson (wndw.ms/y3gB0J), der zeigt, wie Sie die neuen "StateTriggers" und den "UserInteractionMode" zum Erstellen Ihrer eigenen "Continuum StateTrigger" verwenden können.

Adaptive Apps

Apps, die auf Änderungen der Bildschirmgröße und -ausrichtung reagieren können, sind nützlich, doch zum Erzielen von überzeugender, plattformübergreifender Funktionalität bietet die UWP Entwicklern zwei weitere Arten von adaptivem Verhalten:

  • Versionsabhängig adaptive Apps reagieren auf verschiedene Versionen der UWP, indem verfügbare APIs und Ressourcen erkannt werden. Beispiel: Sie möchten, dass Ihre App einige neuere APIs verwendet, die nur auf Geräten vorhanden sind, auf denen die neuesten Versionen der UWP ausgeführt werden, während Sie Kunden weiter unterstützen möchten, die noch kein Upgrade ausgeführt haben.
  • Plattformabhängig adaptive Apps reagieren auf die besonderen Funktionen, die für verschiedene Gerätefamilien verfügbar sind. Eine App kann also so entwickelt werden, dass sie auf allen Gerätefamilien läuft, doch Sie können verschiedene spezifische mobile APIs nutzen, wenn sie auf einem mobilen Gerät wie einem Smartphone ausgeführt wird.

Wie bereits erwähnt, können Apps unter Windows 10 auf die große Mehrheit von UWP-APIs zugreifen, und zwar unabhängig vom Gerät, auf denen sie ausgeführt werden. Spezialisierte APIs für jede Gerätefamilie erlauben Entwicklern nach Wunsch eine weitere Anpassung ihrer Apps.

Die grundlegende Idee hinter adaptiven Apps ist, dass Ihre App eine Prüfung auf die benötigten Funktionen (oder Features) durchführt und diese nur nutzt, sofern sie verfügbar sind. Bislang überprüft eine App die Betriebssystemversion und ruft dann die APIs auf, die dieser Version zugeordnet sind. Unter Windows 10 kann Ihre App zur Laufzeit prüfen, ob eine Klasse, Methode, Eigenschaft, ein Ereignis oder API-Vertrag vom aktuellen Betriebssystem unterstützt wird. Falls ja, ruft die App anschließend die entsprechende API auf. Die "ApiInformation"-Klasse im "Windows.Foundation.Metadata"-Namespace enthält mehrere statische Methoden (wie "IsApiContractPresent", "IsEventPresent" und "IsMethodPresent"), die zum Abfragen von APIs verwendet werden. Im Folgenden finden Sie ein Beispiel:

using Windows.Foundation.Metadata;
if(ApiInformation.IsTypePresent("Windows.Media.Playlists.Playlist"))
{
  await myAwesomePlaylist.SaveAsAsync( ... );
}

Dieser Code macht zwei Dinge. Er führt eine Laufzeitprüfung auf das Vorhandensein der "Playlist-Klasse durch und ruft dann die "SaveAsAsync"-Methode für eine Instanz der Klasse auf. Beachten Sie auch, wie einfach es ist, das Vorhandensein eines Typs im aktuellen Betriebssystem mithilfe der "IsTypePresent"-API zu überprüfen ist. Bisher war für eine solche Überprüfung je nach Sprache und Framework "LoadLibrary", "GetProcAddress", "QueryInterface", "Reflection" oder die Verwendung des Schlüsselworts "dynamic" o. a. erforderlich. Beachten Sie den stark typisierten Verweis beim Methodenaufruf. Bei Verwenden von entweder "Reflection" oder "dynamic" geht die statische Diagnose zur Kompilierzeit verloren, die Sie beispielsweise informiert, wenn Sie den Methodennamen falsch geschrieben haben.

Erkennung mithilfe von API-Verträgen

Ein API-Vertrag ist im Wesentlichen eine Gruppe von APIs. Ein hypothetischer API-Vertrag kann z. B. eine Gruppe von APIs mit zwei Klassen, fünf Schnittstellen, einer Struktur, zwei Enumerationen usw. umfassen. Wir gruppieren logisch verwandte Typen in einem API-Vertrag. In vielerlei Hinsicht stellt ein API-Vertrag ein Feature dar, d. h. eine Gruppe verwandter APIs, die zusammen eine bestimmte Funktionalität bieten. Jede Windows Runtime-API ab Windows 10 gehört zu einem bestimmten API-Vertrag. In der Dokumentation unter msdn.com/dn706135 wird die Vielfalt verfügbarer API-Verträge beschrieben. Sie sehen, dass die meisten davon eine Gruppe funktional verwandter APIs darstellen.

Die Nutzung von API-Verträgen bietet Ihnen als Entwickler einige zusätzliche Garantien. Die wichtigste ist, dass wenn eine Plattform eine beliebige API in einem API-Vertrag implementiert, sie alle APIs in diesem Vertrag implementieren muss. Anders ausgedrückt, ist ein API-Vertrag eine atomische Einheit, und das Testen auf Unterstützung dieses API-Vertrags entspricht dem Testen, ob alle APIs in der Gruppe unterstützt werden. Ihre API kann alle APIs im erkannten API-Vertrag aufrufen, ohne jede API einzeln überprüfen zu müssen.

Der größte und am meisten verwendete API-Vertrag ist "Windows.Foundation.UniversalApiContract", der nahezu alle APIs in der universellen Windows-Plattform enthält. Wenn Sie prüfen möchten, ob das aktuelle Betriebssystem "UniversalApiContract" unterstützt, müssen Sie den folgenden Code schreiben:

if (ApiInformation.IsApiContractPresent(
  "Windows.Foundation.UniversalApiContract"), 1, 0)
{
  // All APIs in the UniversalApiContract version 1.0 are available for use
}

Bislang gibt es nur Version 1.0 von "UniversalApiContract", weshalb diese Prüfung nicht besonders sinnvoll ist. Doch bei einem künftigen Update von Windows 10 könnten weitere APIs eingeführt werden, die zu Version 2.0 von "UniversalApiContract" mit den neuen universellen APIs führen könnten. In Zukunft könnte eine App, die auf allen Geräten laufen soll, aber auch die APIs der neuen Version 2.0 verwenden soll, den folgenden Code verwenden:

if (ApiInformation.IsApiContractPresent(
  "Windows.Foundation.UniversalApiContract"), 2, 0)
{
  // This device supports all APIs in UniversalApiContract version 2.0
}

Wenn Ihre App nur eine einzige Methode aus Version 2.0 abrufen müsste, könnte sie direkt mithilfe von "IsMethodPresent" eine Überprüfung auf die Methode durchführen. In diesem Fall können Sie Ihren bevorzugten Ansatz befolgen.

Neben "UniversalApiContract" gibt es noch weitere API-Verträge. Die meisten stellen ein Feature bzw. eine Gruppe von APIs dar, die nicht für alle Windows 10-Plattformen universell vorhanden und stattdessen für eine oder mehrere bestimmte Gerätefamilien vorhanden sind. Wie bereits erwähnt, müssen Sie nicht länger auf einem bestimmten Typ von Gerät prüfen und anschließend Unterstützung für eine API ableiten. Überprüfen Sie lediglich auf die Gruppe von APIs, die Ihre App verwenden soll.

Ich kann nun mein vorheriges Beispiel so umschreiben, dass eine Prüfung auf das Vorhandensein von "Windows.Media.Playlists.PlaylistsContract" erfolgt, anstatt nur das Vorhandensein der "Playlist"-Klasse zu prüfen:

if(ApiInformation.IsApiContractPresent(
  "Windows.Media.Playlists.PlaylistsContract"), 1, 0)
{
  // Now I can use all Playlist APIs
}

Immer wenn Ihre App eine API abrufen muss, die nicht in allen Gerätefamilien vorhanden ist, müssen Sie einen Verweis auf das entsprechende Erweiterungs-SDK hinzufügen, das die API definiert. Wechseln Sie in Visual Studio 2015 zum Dialogfeld "Verweis hinzufügen", und öffnen Sie die Registerkarte "Erweiterungen". Hier finden Sie die drei wichtigsten Erweiterungen: "Mobile Extension", "Desktop Extension" und "IoT Extension".

Alles, was Ihre App tun muss, ist jedoch, das Vorhandensein des gewünschten API-Vertrags zu prüfen und die entsprechenden APIs bedingt aufzurufen. Um den Gerätetyp müssen Sie sich keine Gedanken machen. Die Frage lautet nun: Ich muss die "Playlist"-API aufrufen, die aber keine universell verfügbare API ist. In der Dokumentation (bit.ly/1QkYqky) erfahre ich, in welchem API-Vertrag sich die Klasse befindet. Doch in welchem Erweiterungs-SDK wird sie definiert?

Wie sich herausstellt, ist die "Playlist"-Klasse (derzeit) nur für Desktopgeräte und nicht für mobile, Xbox- und andere Gerätefamilien verfügbar. Deshalb müssen Sie einen Verweis auf das Desktop Extension SDK hinzufügen, ehe der vorherige Code kompiliert wird.

Lucian Wischik, ein Mitglied des Visual Studio-Teams und gelegentlicher Autor für das MSDN Magazine, hat ein Tool erstellt, das helfen kann. Es analysiert Ihren App-Code, wenn dieser eine plattformspezifische API aufruft, und überprüft, ob eine Adaptivitätsprüfung dafür erfolgt ist. Falls keine Prüfung stattgefunden hat, meldet das Analysemodul eine Warnung und bietet eine praktische Schnellkorrektur durch Einfügen der ordnungsgemäßen Prüfung in den Code, indem einfach STRG+Punkt gedrückt oder auf die Glühbirne geklickt wird. Weitere Informationen finden Sie unter bit.ly/1JdXTeV. Das Analysemodul kann auch über NuGet (bit.ly/1KU9ozj) installiert werden.

Nun wollen wir uns umfassenderen Beispielen der adaptiven Programmierung für Windows 10 zuwenden. Hier ist zunächst Code, der nicht ordnungsgemäß adaptiv ist:

// This code will crash if called from IoT or Mobile
async private Task CreatePlaylist()
{
  StorageFolder storageFolder = KnownFolders.MusicLibrary;
  StorageFile pureRockFile = await storageFolder.CreateFileAsync("myJam.mp3");
  Windows.Media.Playlists.Playlist myAwesomePlaylist =
    new Windows.Media.Playlists.Playlist();
  myAwesomePlaylist.Files.Add(pureRockFile);
  // Code will crash here as this is a Desktop-only call
  await myAwesomePlaylist.SaveAsAsync(KnownFolders.MusicLibrary,
    "My Awesome Playlist", NameCollisionOption.ReplaceExisting);
}

Jetzt wollen wir demselben Code eine Zeile hinzufügen, die überprüft, ob die optionale API auf dem Zielgerät unterstützt wird, ehe die Methode aufgerufen wird. Dadurch werden Abstürze zur Laufzeit verhindert. Dieses Beispiel möchten Sie bestimmt dahingehend weiterführen, dass nicht die UI angezeigt wird, die die "CreatePlaylist"-Methode aufruft, wenn Ihre App erkennt, dass die Wiedergabelistenfunktion auf dem Gerät nicht verfügbar ist:

async private Task CreatePlaylist()
{
  StorageFolder storageFolder = KnownFolders.MusicLibrary;
  StorageFile pureRockFile = await storageFolder.CreateFileAsync("myJam.mp3");
  Windows.Media.Playlists.Playlist myAwesomePlaylist =
    new Windows.Media.Playlists.Playlist();
  myAwesomePlaylist.Files.Add(pureRockFile);
  // Now I'm a safe call! Cache this value if this will be queried a lot
  if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
    "Windows.Media.Playlists.Playlist"))
  {
      await myAwesomePlaylist.SaveAsAsync(
        KnownFolders.MusicLibrary, "My Awesome Playlist",
        NameCollisionOption.ReplaceExisting);
  }
}

Hier ist abschließend ein Beispiel mit Code, der versucht, auf die Kamerataste zuzugreifen, die auf vielen Mobilgeräten zu finden ist:

// Note: Cache the value instead of querying it more than once
bool isHardwareButtonsAPIPresent =
  Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
  "Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
  Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
    HardwareButtons_CameraPressed;
}

Beachten Sie den Erkennungsschritt. Wenn ich auf einem Desktop-PC direkt auf das "HardwareButtons"-Objekt für das "CameraPressed"-Ereignis verweisen würde, ohne zu prüfen, ob "HardwareButtons" vorhanden ist, würde meine App abstürzen.

Es tut sich also viel bei der reaktionsfähigen UI und adaptiven Apps unter Windows 10. Möchten Sie mehr erfahren? Hören Sie sich den großartigen Vortrag von Brent Rector an, den er auf der Build 2015-Konferenz zu API-Verträgen gehalten hat (wndw.ms/IgNy0I), und sehen sich unbedingt das informative Microsoft Virtual Academy-Video zu adaptivem Code an (bit.ly/1OhZWGs), in dem dieses Thema detaillierter behandelt wird.


Clint Rutkasist leitender Produktmanager für Windows mit Schwerpunkt auf der Entwicklerplattform. Er hat an Halo bei 343 Industries und für Channel 9 bei Microsoft gearbeitet und einige verrückte Projekte mit Windows-Technologie realisiert, so z. B. eine computergesteuerte Discotanzfläche, einen kundenspezifischen Ford Mustang, T-Shirts schießende Roboter und mehr.

Rajen Kishnaarbeitet derzeit als ein leitender Produktmarketingmanager im Windows Platform Developer Marketing-Team für Microsoft in Redmond, Washington, USA. Zuvor hat er als Berater und Technical Evangelist für Microsoft in den Niederlanden gearbeitet.

Unser Dank gilt den folgenden technischen Experten von Microsoft für die Durchsicht dieses Artikels: Sam Jarawan, Harini Kannan und Brent Rector