Nick's .NET Travels

Continually looking for the yellow brick road so I can catch me a wizard....

Building Xbox One applications with the Universal Windows Platform

When building a Universal Windows Platform application there are times when you’ll want a different layout/functionality for a particular platform. For the most part building applications across desktop and phone, other than dealing with different screen sizes and orientation, as a developer you can rely on a similar interaction model: mouce clicks and taps equate to roughly the same interaction for most applications. However, this is not the case with the Xbox – the interaction model using either the media remote or a controller relies on a focus state moving around the screen, followed by pressing the action button to select the currently focussed item. In addition to making sure that every control has an appropriate “in focus” visual, it’s essential to make sure that the flow of focus makes sense and that the user can’t get lost in the application (eg nothing focussed, or nothing appearing to be in focus, on the screen).

The different interaction model between desktop/mobile and Xbox means that you’ll often want to present a different layout, or perhaps expose different functionality on Xbox. There are a number of ways to handle this both in XAML and in code:

1. [C#] The device family can be detected using DeviceFamily property. This returns values such as Windows.Mobile, Windows.Desktop and Windows.Xbox which can be used to define business logic that may be platforms specific. Note that the family name for Surface Hub is Windows.Team

var family = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily

2. [XAML] The device family can be used to trigger different visual states. There are a number of state triggers that have been packaged together as a NuGet package - https://github.com/dotMorten/WindowsStateTriggers.

<VisualStateManager.VisualStateGroups>
     <VisualStateGroup x:Name="PlatformStates">
            <VisualState x:Name="Xbox">
             <VisualState.Setters>
                 <Setter Target="textBlock.(TextBlock.Text)"
                         Value="Running on Xbox" />
             </VisualState.Setters>
             <VisualState.StateTriggers>
                 <WindowsStateTriggers:DeviceFamilyStateTrigger DeviceFamily="Xbox" />
             </VisualState.StateTriggers>
         </VisualState>
         … other platform states …
     </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

3. [XAML] Use different XAML files for each device family

Main.xaml  // The default XAML file

Main.DeviceFamily-Xbox.xaml  // An Xbox specific XAML file defined within the file name

/DeviceFamily-Xbox/Main.xaml // An Xbox specific XAML file defined using a folder to group together platform specific files.

Using these three different methodds might seem easy enough at first but you start to realise how frustrating it is when you want to work on a specific feature (for example navigation) but you don’t have a specific device with you (for example there’s no Xbox nearby for running the app on). To at least partial solve this problem, here are three tips that will allow you to work on your Xbox app on your desktop.

1. [C#] Instead of referencing the AnalyticsInfo class, we can add a wrapper class that allows us to override the device family whilst debugging the application. Use DeviceInfo.DeviceFamily instead of AnalyticsInfo.VersionInfo.DeviceFamily

#if DEBUG
#define DEBUG_PLATFORM_XBOX
#endif

public static class DeviceInfo
{
     public static string DeviceFamily
     {
         get
         {
#if DEBUG_PLATFORM_XBOX
             return "Windows.Xbox";
#else
             return AnalyticsInfo.VersionInfo.DeviceFamily;
#endif
         }
     }
}

In this case the compilation constant DEBUG_PLATFORM_XBOX is used to override the actual DeviceFamily value. Note we’ve wrapped this using a #if for the DEBUG constant – this prevents the override accidentally being deployed as part of a release build.

2. [XAML] The DeviceFamilyStateTrigger (see https://github.com/dotMorten/WindowsStateTriggers/blob/master/src/WindowsStateTriggers/DeviceFamilyStateTrigger.cs) uses the DeviceFamily returned by the AnalyticsInfo class. A clone of this trigger can be made that relies on DeviceInfo.DeviceFamily (from [1]); this would activate states based on the overridden device family value.

3. [XAML] In order to debug the Xbox layout (eg MainPage.DeviceFamily-Xbox.xaml) on a desktop machine, simply rename the file to specify the Desktop device family (ie MainPage.DeviceFamily-Desktop.xaml).

Combining these three tips allows for the majority of the application to look and feel like it would when running on an Xbox. Unfortunately some of the built in components do render differently on desktop and xbox – they will always render as per the actual device family, despite attempts to override this value.

Comments are closed