{"id":6000,"date":"2015-06-17T12:00:17","date_gmt":"2015-06-17T10:00:17","guid":{"rendered":"http:\/\/www.centigrade.de\/blog\/?p=6000"},"modified":"2019-01-21T09:15:37","modified_gmt":"2019-01-21T08:15:37","slug":"kontextsensitive-user-interfaces-mit-der-universal-windows-platform","status":"publish","type":"blog","link":"https:\/\/www.centigrade.de\/de\/blog\/kontextsensitive-user-interfaces-mit-der-universal-windows-platform\/","title":{"rendered":"Kontextsensitive User Interfaces mit der Universal Windows Platform"},"content":{"rendered":"<p>Vor kurzem habe ich auf der <a title=\"Webseite der dotnet Cologne\" href=\"http:\/\/dotnet-cologne.de\/\" target=\"_blank\">dotnet Cologne<\/a>\u00a0und auch\u00a0auf der <a href=\"http:\/\/www.developer-week.de\/\" target=\"_blank\">DWX Developer Week<\/a> einen Vortrag mit dem Titel &#8222;4K und andere Herausforderungen &#8211; Next Generation Desktop UIs f\u00fcr Windows 10&#8220; gehalten. Der Vortrag hat den Begriff der <em>Universal App Platform<\/em> auf Windows 10 beleuchtet und was ein Entwickler dieser entlocken kann, um zukunftsorientierte User Interfaces umzusetzen. Folgender Blogbeitrag soll nicht nur diejenigen erreichen, die meine Session besuchen konnten, sondern auch diejenigen, die nicht vor Ort waren. Der Artikel soll dar\u00fcber hinaus noch tiefergehende Informationen zur Thematik liefern. Analog zu meiner Session, in der es gegen Ende einen Live-Coding-Teil gab, wird es auch hier schlie\u00dflich Code geben, wobei ein paar der neuen Universal App Features exemplarisch zu sehen sind.<!--more--><\/p>\n<h3>R\u00fcckblick auf Windows 8<\/h3>\n<div style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Windows8-SampleScreen.jpg\" alt=\"Windows 8 Startbildschim\" width=\"670\" \/><p class=\"wp-caption-text\">Windows 8 Startbildschim (Quelle: <a title=\"MS News Center (Windows 8)\" href=\"http:\/\/news.microsoft.com\/?attachment_id=24896\" target=\"_blank\">Microsoft News Center<\/a>)<\/p><\/div>\n<p><em>One UI to rule them all<\/em>, das war der Eindruck, den Windows 8 im Jahr 2012 wohl bei den meisten Anwendern vermittelte. Die neue touch-orientierte, grelle Kacheloberfl\u00e4che und das fehlende Startmen\u00fc stellten f\u00fcr viele Nutzer einen starken Konsistenzbruch dar. F\u00fcr den Endbenutzer weniger sichtbar, tat sich zu der Zeit auch aus Entwicklersicht einiges. Im Sinne der <a title=\"Platform Convergence Journey im MVA Video\" href=\"http:\/\/www.microsoftvirtualacademy.com\/training-courses\/a-developers-guide-to-windows-10\" target=\"_blank\">Platform Convergence Journey<\/a> wurde mit Einf\u00fchrung von Windows 8 der Betriebssystem-Kernel zwischen Xbox, Windows 8 und Windows Phone 8 vereinheitlicht. Mit Windows 8.1 wurde dann das App-Modell zusammengef\u00fchrt. Bereits damals war es unter dem Begriff <a title=\"Visual Studio Blog (Universal Apps mit Shared Projects)\" href=\"http:\/\/blogs.msdn.com\/b\/visualstudio\/archive\/2014\/04\/14\/using-visual-studio-to-build-universal-xaml-apps.aspx\" target=\"_blank\"><em>Universal App<\/em><\/a> schon m\u00f6glich eine Windows Store App mit einer App Identit\u00e4t und m\u00f6glichst gleicher Codebasis f\u00fcr Desktops und Smartphones zu erschaffen, wenn auch etwas umst\u00e4ndlich.<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/PlatformConvergence-Illustration.png\" alt=\"Platform Convergence Journey\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Platform Convergence Journey (Quelle: <a title=\"Microsoft Virtual Academy - Developers Guide to Windows 10\" href=\"http:\/\/www.microsoftvirtualacademy.com\/training-courses\/a-developers-guide-to-windows-10\" target=\"_blank\">Screencapture Microsoft Virtual Academy<\/a>)<\/p><\/div>\n<h3>Die Windows 10 Philosophie<\/h3>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Windows10-SampleScreen02.jpg\" alt=\"Windows 10 Desktop und Startmen\u00fc\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Windows 10 Desktop und Startmen\u00fc (Quelle: <a title=\"MS News Center (Windows 10)\" href=\"http:\/\/news.microsoft.com\/?attachment_id=115511\" target=\"_blank\">Microsoft News Center<\/a>)<\/p><\/div>\n<p>Mit Windows 10 erscheint es zun\u00e4chst so, als gehe Microsoft wieder einen Schritt zur\u00fcck. Aus Sicht eines Desktopnutzers ist dies sicherlich richtig. Windows Store Apps k\u00f6nnen im Fenster laufen, es gibt wieder ein klassisches Startmen\u00fc in Verbindung mit einigen Kacheln und Touchbedienung ist nun nicht mehr der Standardfall. Nur wenn Windows beispielweise auf einem Tablet l\u00e4uft, wird das UI spezifisch angepasst. Aus Entwicklersicht geht man jedoch weiterhin einen konsequenten Weg in Richtung Vereinheitlichung: K\u00fcnftig gibt es keine Trennung mehr von Windows Versionen f\u00fcr verschiedene Ger\u00e4te. <em>Das Windows 10<\/em> wird auf allen Ger\u00e4ten gleicherma\u00dfen laufen, ob Smartphone, Desktop, Xbox, Surface Hub und sogar HoloLens oder IoT Ger\u00e4te wie der RaspberryPi. Unter der sogenannten <a title=\"Guide to Universal Windows Platform (UWP) apps\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dn894631.aspx\" target=\"_blank\">Universal Windows Platform<\/a> wird auch eine k\u00fcnftige Windows App auf allen Ger\u00e4ten gleicherma\u00dfen laufen &#8211; und dies im Sinne von <em>write once, deploy everywhere<\/em>.<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/UniversalWindowsPlatform-Illustration.png\" alt=\"Universal Windows Platform\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Universal Windows Platform (Quelle: <a title=\"MS Blog (First Look at the Windows 10 Universal App Platform)\" href=\"http:\/\/blogs.windows.com\/buildingapps\/2015\/03\/02\/a-first-look-at-the-windows-10-universal-app-platform\/\" target=\"_blank\">Microsoft Blog<\/a>)<\/p><\/div>\n<p>Der Entwickler entwickelt fortan eine App \u2013 wirklich ein Binary \u2013 welche auf allen Ger\u00e4ten ver\u00f6ffentlicht wird und direkt lauff\u00e4hig ist. Dies soll jedoch auf keinen Fall bedeuten, dass die Anwendung auf allen Ger\u00e4ten gleich erscheint. Vielmehr sollen die Entwickler die UI an die verschiedenen Endger\u00e4te anpassen, sei es eine Smartwatch, eine mobile Line-of-Business App, eine Desktop-Anwendung oder ein UI f\u00fcr eine K\u00fchlschranksteuerung im Internet of Things. Durch das <a title=\"Wikipedia: MVVM\" href=\"http:\/\/de.wikipedia.org\/wiki\/Model_View_ViewModel\" target=\"_blank\">MVVM Pattern<\/a> und eine saubere Schichtentrennung ist dies sehr gut m\u00f6glich, da sich die interne Gesch\u00e4ftslogik von der austauschbaren, anpassbaren und hochoptimierten Darstellungsschicht trennen l\u00e4sst.<\/p>\n<div id=\"attachment_6216\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6216\" class=\"size-full wp-image-6216\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/MVVM-Illustration-Centigrade1.png\" alt=\"MVVM: Model-View-ViewModel Softwareschichtung\" width=\"670\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/MVVM-Illustration-Centigrade1.png 2560w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/MVVM-Illustration-Centigrade1-300x169.png 300w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/MVVM-Illustration-Centigrade1-1024x576.png 1024w\" sizes=\"(max-width: 2560px) 100vw, 2560px\" \/><p id=\"caption-attachment-6216\" class=\"wp-caption-text\">MVVM: Model-View-ViewModel Softwareschichtung<\/p><\/div>\n<h3>Spezialisierte UIs<\/h3>\n<p>Wie sieht nun diese Spezialisierung aus? Wo und welche Anpassungen sind f\u00fcr verschiedene Ger\u00e4te n\u00f6tig? Welche Mittel bieten sich mir als Entwickler meine UI anzupassen? Wie filtere ich technisch verschiedene Ger\u00e4teklassen und nehme diesbez\u00fcglich Anpassungen vor?<\/p>\n<p>Die intuitivste Komponente, die einem in den Sinn kommt, wenn man an verschiedene Ger\u00e4te denkt, sind die verschiedenen Formfaktoren, wie Displaygr\u00f6\u00dfe, Aufl\u00f6sung und daraus resultierend die physikalische \u2013 sprich vom Ger\u00e4t gegebene \u2013 Pixeldichte. Nicht zu vergessen ist in diesem Zusammenhang auch die Entfernung zum Betrachter: der Sichtabstand. Um dies kurz zusammen zu fassen, kann man sagen, eine h\u00f6here <a title=\"Centigrade Blog: Aufl\u00f6sungsunabh\u00e4ngiges Icon Design\" href=\"http:\/\/www.centigrade.de\/de\/blog\/aufloesungsunabhaengiges-icon-design-teil-1\" target=\"_blank\">physikalische Aufl\u00f6sung<\/a> auf kleinerer physikalischer Bildschirmdiagonalen bedeutet eine h\u00f6here Pixeldichte, auch PPI (pixel per inch) genannt. Diese wird umso wichtiger, je n\u00e4her der Betrachter dem Ger\u00e4t ist. Daher sind hochaufl\u00f6sende Displays bei Smartphones keine Besonderheit mehr. Man kann h\u00f6here PPI nutzen, um entweder mehr Inhalt auf gleicher Fl\u00e4che unterzubringen, was nur bis zu einem bestimmten Grad sinnvoll ist, oder man kann gleichen Inhalt in besserer Qualit\u00e4t darstellen. Runde Formen, die auf digitalen Ger\u00e4ten immer nur Ann\u00e4herungen sind, k\u00f6nnen so ihrer Idealdarstellung immer n\u00e4her kommen. F\u00fcr den Nutzer erscheint die Anwendungsoberfl\u00e4che dann crisp und smooth.<\/p>\n<p>Es reicht oft aber nicht, nur diese Faktoren zu betrachten. Mit dem aus dem Web stammenden <a title=\"Wikipedia: Responsive Webdesign\" href=\"http:\/\/de.wikipedia.org\/wiki\/Responsive_Webdesign\" target=\"_blank\"><em>Responsive Design<\/em><\/a> unterscheidet man beispielsweise Desktop und Smartphone anhand der Aufl\u00f6sung und macht beispielsweise zweispaltigen Inhalt einspaltig, zeigt nur noch die essentiellen Inhalte an oder verschiebt sie in sekund\u00e4re Navigationslevel. Dies ist ein erster Schritt, der jedoch schnell an seine Grenzen st\u00f6\u00dft. Responsive Design ist relativ technisch motiviert und ber\u00fccksichtigt zun\u00e4chst nur Ger\u00e4teparameter. Bezieht man beim UX Design die Benutzerrolle und den aktuellen Nutzungskontext mit ein, kommt man zu deutlich besseren, intuitiveren Ergebnissen. Diese essentielle Ber\u00fccksichtigung des Nutzers nennt sich kontextsensitives Design.<\/p>\n<h3>Kontextsensitives Design<\/h3>\n<div id=\"attachment_6027\" style=\"width: 310px\" class=\"wp-caption alignleft\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-6027\" class=\"size-medium wp-image-6027\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-HoloLens-Device-300x169.jpg\" alt=\"Microsoft HoloLens\" width=\"300\" height=\"169\" srcset=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-HoloLens-Device-300x169.jpg 300w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-HoloLens-Device-1024x576.jpg 1024w, https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-HoloLens-Device.jpg 1440w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><p id=\"caption-attachment-6027\" class=\"wp-caption-text\">Microsoft HoloLens (Quelle: <a title=\"MS News Center (HoloLens)\" href=\"http:\/\/news.microsoft.com\/?attachment_id=197511\" target=\"_blank\">Microsoft News Center<\/a>)<\/p><\/div>\n<p>Extrembeispiele, die von kontextsensitivem Design profitieren w\u00e4ren beispielsweise Anwendungen f\u00fcr Virtual Reality und Augmented Reality Ger\u00e4te. Denn was bedeutet der Begriff Aufl\u00f6sung f\u00fcr diese Ger\u00e4teklassen? F\u00fcr eine VR-Brille ist eine hohe Aufl\u00f6sung in erster Linie wichtig damit der Benutzer kein st\u00f6rendes <em>Fliegengitter<\/em> vor seinem Auge erkennt, schlie\u00dflich ist das Display in sehr geringem Abstand davor. Viel wichtiger ist an dieser Stelle die wahrgenommene Aufl\u00f6sung und wie das UI in der 3D-Szene der VR- oder AR-Anwendung platziert ist. Wie in <a title=\"Keynote Build 2015\" href=\"http:\/\/channel9.msdn.com\/Events\/Build\/2015\/KEY01\" target=\"_blank\">Microsofts Keynote der Build 2015<\/a> zu sehen, k\u00f6nnten zum Beispiel UI Elemente im realen Raum platziert werden. Mit klassischem Responsive Design l\u00e4sst sich solch eine Herausforderung nur schlecht l\u00f6sen.<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-HoloLens-Skype.jpg\" alt=\"Microsoft HoloLens: Konzept einer Augmented Reality Anwendung\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Microsoft HoloLens: Konzept einer Augmented Reality Anwendung (Quelle: <a title=\"MS News Center (HoloLens)\" href=\"http:\/\/news.microsoft.com\/?attachment_id=152383\" target=\"_blank\">Microsoft News Center<\/a>)<\/p><\/div>\n<p>Dabei gen\u00fcgt es bereits sich, allein den Desktop \u2013 also ein station\u00e4rer Rechner \u2013 zu betrachten, sei es ein B\u00fcro-PC, ein Konferenzmonitor oder ein gro\u00dfer Screen in einer Leitwarte einer Raumstation. Auch hier kommt man schnell in Situationen, die mit Responsive Design allein nicht zu l\u00f6sen sind.<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/ESA-ControlRoom.jpg\" alt=\"Kontrollraum der esa Raumstation\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Kontrollraum der esa Raumstation (Quelle: <a title=\"Gallerie esa Homepage\" href=\"http:\/\/www.esa.int\/spaceinimages\/Images\/2012\/06\/Main_Control_Room_at_ESA_s_Space_Operations_Centre\" target=\"_blank\">esa Homepage<\/a>)<\/p><\/div>\n<p>Es gibt so manche Entwickler, die mit Monitoren in hochkant-Ausrichtung arbeiten. Gibt es Anwendungen, die darauf eingehen, ob der Monitor hochkant gestellt wurde? Pair-Programming Sessions oder walkthrough-artige Codereviews finden mit mehreren Personen vor einem Bildschirm statt. Dabei stehen manche Personen eventuell n\u00e4her am Bildschirm, andere weiter weg. Welche Anwendungen ber\u00fccksichtigen diese Szenarien?<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Typical-Office.jpg\" alt=\"Ein typischer Desktop?\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Ein typischer Desktop?<\/p><\/div>\n<p><a title=\"Microsoft Surface Hub\" href=\"https:\/\/www.microsoft.com\/microsoft-surface-hub\/en-us\" target=\"_blank\">Microsofts Surface Hub<\/a> ist ein riesiger Konferenzbildschirm mit 84 Zoll, mehreren Kameras, ausgerichteten Mikrofonen und Stifteingabe. Der Pr\u00e4sentator steht direkt vor dem Ger\u00e4t und kann \u00fcber einen Stift direkt in Anwendungen zeichnen, viele Betrachter sitzen in einiger Entfernung und beobachten das Geschehen und es k\u00f6nnen sogar Teilnehmer nur remote zugeschaltet sein, die aber gleichen Inhalt auf Ihrem heimischen PC sehen. Bisher ist mir keine Meeting-Anwendung bekannt, die ohne Umstellungen auf solch einen Fall optimiert w\u00e4re.<\/p>\n<div id=\"attachment_6036\" style=\"width: 680px\" class=\"wp-caption alignnone\"><img decoding=\"async\" aria-describedby=\"caption-attachment-6036\" src=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/Microsoft-SurfaceHub-Meeting01.jpg\" alt=\"Microsoft Surface Hub in Meetings\" width=\"670\" \/><p id=\"caption-attachment-6036\" class=\"wp-caption-text\">Microsoft Surface Hub in Meetings (Quelle: <a title=\"MS News Center (Surface Hub)\" href=\"http:\/\/news.microsoft.com\/?attachment_id=197511\" target=\"_blank\">Microsoft News Center<\/a>)<\/p><\/div>\n<p>Solche Herausforderungen, die sich breit ausgerichteten Universal Apps stellen, k\u00f6nnen nur durch kontextsensitives Design auf dem UI gel\u00f6st werden. Dabei kennt die Anwendung ihren Nutzungskontext und reagiert dementsprechend. Durch im Ger\u00e4t vorhandene Eye-Tracking-Sensoren k\u00f6nnte der Sichtabstand des Betrachters erkannt und Anwendungen dementsprechend angepasst werden. Eine App wei\u00df, ob sie auf einem hochkant ausgerichteten Monitor l\u00e4uft und optimiert Ihren Inhalt auf dieses Szenario. Erst wenn das Ger\u00e4t \u00fcber ein Mikrofon als Eingabeger\u00e4t verf\u00fcgt, wird beispielsweise Push-To-Talk-Funktionalit\u00e4t eingeblendet. Es gibt hier zahlreiche Herausforderungen, die nur gut gel\u00f6st werden k\u00f6nnen, wenn man den Nutzer nicht aus den Augen verliert. Aus technischer Sicht h\u00f6rt sich das f\u00fcr einen Entwickler jedoch nach sehr viel Zusatzarbeit an. Das Auslesen von Eye-Tracking Informationen und darauf reagierende Layout- und Inhaltsoptimierungen erscheinen wie eine Herkulesaufgabe. Der Entwickler bekommt mit Windows 10, Visual Studio 2015 und der Universal App Platform neue Features, die eine gute Unterst\u00fctzung bieten, um kontextsensitive Software mit guter User Experience entwickeln zu k\u00f6nnen. Im Folgenden sollen ein paar dieser Werkzeuge betrachtet werden.<\/p>\n<h3>UWP Features unter Windows 10<\/h3>\n<p>Wie schon in WPF die <a title=\"WPF Text Measurement Units\" href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/learnwin32\/dpi-and-device-independent-pixels\" target=\"_blank\">device independent pixels<\/a>, geht Microsoft bei der UWP einen Schritt weiter in Hinsicht eines abstrakten Pixelbegriffs und f\u00fchrt die sogenannten <a title=\"Designing with effective pixels\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/apps\/dn958435.aspx#Designing_with_effective_pixels\" target=\"_blank\"><em>effective pixels<\/em><\/a> ein. Diese basieren auf der Pixeldichte des Ger\u00e4tes und eines heuristischen Sichtabstands. Daraus ergibt sich eine abstrakte Pixelinformation, sodass der Entwickler sich nicht mehr um diese physikalischen Details k\u00fcmmern muss. Auf allen Ger\u00e4ten <em>erscheinen<\/em> dem Betrachter demnach die Elemente in gleicher Gr\u00f6\u00dfe.<\/p>\n<p>Weiterhin gibt es mit dem <a title=\"RelativePanel (MSDN)\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows.ui.xaml.controls.relativepanel.aspx\" target=\"_blank\">RelativePanel<\/a> einen neuen Layoutcontainer, der es recht einfach m\u00f6glich macht, die Elemente innerhalb des Containers in Relation zueinander anzuordnen. Das ist besonders hilfreich, wenn sich das Layout dynamisch verhalten soll. Musste man fr\u00fcher ein Custom-Panel implementieren oder recht komplexe Umstellungen eines Grids durchf\u00fchren, so kann man nun das RelativePanel verwenden.<\/p>\n<p>Um auf verschiedene Ger\u00e4teklassen und Formfaktoren zu reagieren, wollen wir uns im Folgenden die sogenannten <a title=\"Guide to Universal Windows Platform (UWP) apps\" href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dn894631.aspx#Use_visual_state_triggers_to_build_UI_that_can_adapt_to_available_screen_space\" target=\"_blank\">VisualState-Trigger<\/a> etwas genauer anschauen. Der von Microsoft vorgeschlagene Weg f\u00fcr ein adaptives Layout ist die Verwendung des VisualState-Managers und VisualStates f\u00fcr unterschiedliche Zust\u00e4nde der View.<\/p>\n<h2>Beispielimplementierung: Ein eigener VisualState-Trigger<\/h2>\n<p>Stellen wir uns einmal folgendes Szenario vor: Der Nutzer besitzt einen Monitor mit der M\u00f6glichkeit den aktuellen Sichtabstand zu messen (z.B. \u00fcber eine Webcam, ein Headtracking-System, Infrarot, die Kinect o.\u00e4.). Als Entwickler einer Anwendung m\u00f6chte ich nun, dass die Schrift in meiner Anwendung auf den Sichtabstand des Betrachters angepasst wird. Diese sollte f\u00fcr ihn immer gleich gro\u00df erscheinen. Ob er nun sehr nah am Bildschirm (weil er z.B. Notizen mit einem Stift auf einem touch-sensitiven Monitor macht), in normalen Abstand davor oder in einer Pair-Session in etwas Entfernung davon sitzt. Als UI Entwickler m\u00f6chte ich diese \u00c4nderung technisch \u201eerkennen\u201c k\u00f6nnen, um anschlie\u00dfend in XAML recht einfach darauf zu reagieren. Dies soll nun beispielhaft umgesetzt werden. Dabei liegt der Fokus weniger auf der Ausarbeitung einer sch\u00f6nen und vollst\u00e4ndigen Anwendung als vielmehr darauf, die zur Verf\u00fcgung stehenden Features zu demonstrieren.<\/p>\n<p>Zun\u00e4chst erstellen wir ein neues <em>Windows Universal App<\/em> Project, \u00f6ffnen dort die <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\">MainPage.xaml<\/span> und platzieren unseren Text dort. Gleichzeitig f\u00fchren wir examplarisch zwei Visual States ein, f\u00fcr den nahen und fernen Sichtabstand:<br \/>\n<code><\/code><\/p>\n<pre class=\"csharpcode\" style=\"font-size: medium; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">Grid<\/span> <span class=\"attr\" style=\"color: #ff0000;\">Margin<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"25\"<\/span> <span class=\"attr\" style=\"color: #ff0000;\">Background<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"White\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualStateManager.VisualStateGroups<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualStateGroup<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"CommonStates\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n         <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Near\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n            <span class=\"rem\" style=\"color: #008000;\">&lt;!-- Trigger and reaction missing for now. --&gt;<\/span>\r\n         <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n         <span class=\"rem\" style=\"color: #008000;\">&lt;!-- Here could be more states \u2026 --&gt;<\/span>\r\n         <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Far\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n            <span class=\"rem\" style=\"color: #008000;\">&lt;!-- Trigger and reaction missing for now. --&gt;<\/span>\r\n         <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualStateGroup<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualStateManager.VisualStateGroups<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">TextBlock<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Output\"<\/span>\r\n      <span class=\"attr\" style=\"color: #ff0000;\">FontSize<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"20\"<\/span>\r\n      <span class=\"attr\" style=\"color: #ff0000;\">Text<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Lorem ipsum dolor sit amet, consetetur\u2026\"<\/span>\r\n      <span class=\"attr\" style=\"color: #ff0000;\">TextTrimming<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"CharacterEllipsis\"<\/span>\r\n      <span class=\"attr\" style=\"color: #ff0000;\">TextWrapping<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Wrap\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n<span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">Grid<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Momentan ist der <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\"><a title=\"AdaptiveTrigger (MSDN)\" href=\"https:\/\/msdn.microsoft.com\/en-uS\/office\/office365\/windows.ui.xaml.adaptivetrigger.aspx\" target=\"_blank\">AdaptiveTrigger<\/a><\/span> der einzige Trigger, den Microsoft mitliefert. Damit ist es lediglich m\u00f6glich, auf die Gr\u00f6\u00dfe des Bildschirms (gegeben in effective pixels) zu reagieren. Es gibt zun\u00e4chst keine M\u00f6glichkeit auf die hier gestellten Anforderungen zu reagieren. Gl\u00fccklicherweise k\u00f6nnen wir jedoch eigene Trigger schreiben und diese in XAML benutzen. Wir wollen beispielweise in unseren Near-State wechseln, sobald die ViewDistance 12 Zoll unterschreitet und dies per Trigger folgenderma\u00dfen abbilden:<br \/>\n<code><\/code><\/p>\n<pre class=\"csharpcode\" style=\"font-size: medium; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Near\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">triggers:ViewDistanceTrigger<\/span> <span class=\"attr\" style=\"color: #ff0000;\">MaxViewDistance<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"12\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"rem\" style=\"color: #008000;\">&lt;!-- What to do? --&gt;<\/span>\r\n<span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Dieser Trigger muss nun implementiert werden. Dazu kann man von <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\"><a title=\"StateTriggerBase (MSDN)\" href=\"https:\/\/msdn.microsoft.com\/en-uS\/office\/office365\/windows.ui.xaml.statetriggerbase.aspx\" target=\"_blank\">StateTriggerBase<\/a><\/span> ableiten und innerhalb der Klasse \u00fcber die Methode <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\">SetActive<\/span> diesen (de)aktivieren. Der im XAML definierte VisualState wird aktiv, sobald <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\">SetActive(true)<\/span> im aufgerufen wird.<br \/>\nDer Trigger k\u00f6nnte beispielsweise eine Komponente <span style=\"font-family: Consolas, 'Courier New', Courier, Monospace;\">IViewDistanceDetector<\/span> benutzen, welche f\u00fcr die Erkennung des Sichtabstands zust\u00e4ndig ist:<br \/>\n<code><\/code><\/p>\n<pre class=\"csharpcode\" style=\"font-size: medium; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">public<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">class<\/span> ViewDistanceTrigger : StateTriggerBase\r\n{\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">public<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">double<\/span> MinViewDistance { <span class=\"kwrd\" style=\"color: #0000ff;\">get<\/span>; <span class=\"kwrd\" style=\"color: #0000ff;\">set<\/span>; } = 0;\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">public<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">double<\/span> MaxViewDistance { <span class=\"kwrd\" style=\"color: #0000ff;\">get<\/span>; <span class=\"kwrd\" style=\"color: #0000ff;\">set<\/span>; } = <span class=\"kwrd\" style=\"color: #0000ff;\">double<\/span>.PositiveInfinity;\r\n\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">private<\/span> IViewDistanceDetector viewDistanceDetector;\r\n\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">public<\/span> ViewDistanceTrigger()\r\n   {\r\n      viewDistanceDetector = new ViewDistanceDetector();\r\n      viewDistanceDetector.ViewDistanceChanged +=\r\n\t     ViewDistanceDetector_ViewDistanceChanged;\r\n   }\r\n\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">private<\/span> void ViewDistanceDetector_ViewDistanceChanged\r\n      (<span class=\"kwrd\" style=\"color: #0000ff;\">object<\/span> sender, ViewDistanceChangedEventArgs eventArgs)\r\n   {\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">double<\/span> currentViewDistance = eventArgs.ViewDistanceInInch;\r\n   \r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">if<\/span>((currentViewDistance &gt;= MinViewDistance)\r\n\t     &amp;&amp; (currentViewDistance &lt;= MaxViewDistance))\r\n      {\r\n         SetActive(<span class=\"kwrd\" style=\"color: #0000ff;\">true<\/span>);\r\n      }\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">else<\/span>\r\n      {\r\n         SetActive(<span class=\"kwrd\" style=\"color: #0000ff;\">false<\/span>);\r\n      }\r\n   }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Der Einfachheit wollen wir an dieser Stelle lediglich die FontSize unseres TextBlocks \u00e4ndern. Mit den neuen <a title=\"VisualState.Setters (MSDN)\" href=\"https:\/\/msdn.microsoft.com\/en-uS\/office\/office365\/windows.ui.xaml.visualstate.setters.aspx\" target=\"_blank\">Setters im VisualState<\/a> ist diese diskrete \u00c4nderung sogar ohne komplexe Definition von Storyboards m\u00f6glich. Ein Feature was vor allem bei initialen Zustandswechseln hilfreich ist:<br \/>\n<code><\/code><\/p>\n<pre class=\"csharpcode\" style=\"font-size: medium; color: black; font-family: Consolas, 'Courier New', Courier, Monospace; background-color: #ffffff;\"><span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Near\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">triggers:ViewDistanceTrigger<\/span> <span class=\"attr\" style=\"color: #ff0000;\">MaxViewDistance<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"12\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.Setters<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">Setter<\/span> \r\n         <span class=\"attr\" style=\"color: #ff0000;\">Target<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Output.FontSize\"<\/span>\r\n         <span class=\"attr\" style=\"color: #ff0000;\">Value<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"{StaticResource FontSize.Small}\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.Setters<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span> <span class=\"attr\" style=\"color: #ff0000;\">x:Name<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Far\"<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">triggers:ViewDistanceTrigger<\/span> <span class=\"attr\" style=\"color: #ff0000;\">MaxViewDistance<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"25\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.StateTriggers<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.Setters<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n      <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;<\/span><span class=\"html\" style=\"color: #800000;\">Setter<\/span> \r\n         <span class=\"attr\" style=\"color: #ff0000;\">Target<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"Output.FontSize\"<\/span>\r\n         <span class=\"attr\" style=\"color: #ff0000;\">Value<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">=\"{StaticResource FontSize.Large}\"<\/span> <span class=\"kwrd\" style=\"color: #0000ff;\">\/&gt;<\/span>\r\n   <span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState.Setters<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<span class=\"kwrd\" style=\"color: #0000ff;\">&lt;\/<\/span><span class=\"html\" style=\"color: #800000;\">VisualState<\/span><span class=\"kwrd\" style=\"color: #0000ff;\">&gt;<\/span>\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>Selbstverst\u00e4ndlich w\u00e4ren ein animierter, fl\u00fcssiger \u00dcbergang und noch mehrere Zwischenzust\u00e4nde hier w\u00fcnschenswert. Um jedoch sehr knapp zu zeigen, wie man in einer Universal App eigene Trigger schreibt und kontextsensitive Anpassungen am UI vornimmt, sollte das an dieser Stelle gen\u00fcgen. Selbstverst\u00e4ndlich kann dieses Konzept auf eine Reihe anderer kontextbezogener Informationen ausgeweitet werden: Ist mein Monitor hochkant orientiert? Habe ich ein Mikrofon zur Spracheingabe zur Verf\u00fcgung? Ist ein Xbox Controller an meinem Ger\u00e4t angeschlossen? L\u00e4uft meine Anwendung auf einer bestimmten Ger\u00e4teklasse? All diese Informationen k\u00f6nnte man komfortabel in solche Trigger auslagern. Zu hoffen ist auch, dass Microsoft noch weitere eigene Trigger mitliefert und den Entwicklern einen Teil des Implementierungsaufwands abnimmt.<\/p>\n<h3>Fazit<\/h3>\n<p>Windows 10 und die Universal App Platform liefern uns \u2013 wie eben gezeigt \u2013 Hilfsmittel, die UI f\u00fcr verschiedene Endger\u00e4te zu optimieren. Wenn Microsoft verspricht, dass eine App auf allen Ger\u00e4ten gleicherma\u00dfen laufen soll, m\u00fcssen sie dies auch tun. Andererseits kann man diese Tools auch nutzen, um schon allein das Desktop-Erlebnis seiner Anwendung zu optimieren. Erkenntnisse bez\u00fcglich verschiedener Nutzungsszenarien und \u2013rollen, die man bei der Entwicklung von Smartphone UIs kennengelernt hat, kann man auch auf den Desktop \u00fcbertragen. Auch in station\u00e4ren Umgebungen gibt es eine Vielzahl von Kontexten und unterschiedlichen Interaktionsm\u00f6glichkeiten auf die jeweils geeignet reagiert werden muss. Der Desktop ist, was das UX Design betrifft, in vielen F\u00e4llen noch nicht am Ende angekommen. Hier verstecken sich noch viele innovative Konzepte. Diese sollte man entdecken, nutzen und am Ende durch eine herausragende Anwendung beeindrucken.<\/p>\n<h3>Download<\/h3>\n<p>Wer meine Session\u00a0zu Next Generation Desktop UIs f\u00fcr Windows 10 noch ein Mal anhand der Vortragsfolien nachvollziehen m\u00f6chte, kann das hier tun. Ich stelle auch gerne die Code Samples\u00a0von der Live Demo auf der DWX und Code Snippets aus diesem Blogbeitrag zum Download:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/NextGenerationDesktopUIs-Windows10-dotnetCologne-DWX.pdf\">PDF: Vortragsfolien: Next Generation Desktop UIs for Windows 10<\/a><\/li>\n<li><a href=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/DavidWuerfel_NextGenDesktop-CodeSamples-DWX.zip\">ZIP: Code Snippets von der DWX<\/a><\/li>\n<li><a href=\"https:\/\/www.centigrade.de\/wordpress\/wp-content\/uploads\/DavidWuerfel_NextGenDesktop-Blog-CodeSnippets-ViewDistanceSample.zip\">ZIP: Code Snippets von diesem Blogbeitrag<\/a><\/li>\n<\/ul>\n<div class=\"trademark\">Alle auf dieser Webseite erw\u00e4hnten Marken- und Warenzeichen oder Produktnamen sind Eigentum ihrer jeweiligen Inhaber und dienen nur der Beschreibung.<\/div>\n","protected":false},"author":42,"featured_media":0,"template":"","tags":[102,198],"class_list":["post-6000","blog","type-blog","status-publish","hentry","tag-user-interface-design-de","tag-windows-8-de"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog\/6000","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog"}],"about":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/types\/blog"}],"author":[{"embeddable":true,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/users\/42"}],"version-history":[{"count":0,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/blog\/6000\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/media?parent=6000"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.centigrade.de\/de\/wp-json\/wp\/v2\/tags?post=6000"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}