A XAML control displaying Xbox gamepad keys

A XAML control displaying Xbox gamepad keys

When I started working on Dropbox’s Xbox application, I was very surprised that Microsoft didn’t provide a control to display the Xbox controller keys in your XAML UI.

The D-pad navigation is rather limited, so it’s important to provide shortcuts to allow users to quickly access some features. For example, press the “Y” key to search in your application.

To help the user to know which shortcuts are available, a best practice is to display a summary at the bottom-right corner.

In order to help us, I’ve created a little control displaying all the Xbox keys you can override: A, B, X, Y, View, Menu, Play.

To use it:

<control:XboxKeyControl Symbol="X" Margin="6" />

Here is the source code:

<UserControl
    x:Class="Huyn.Controls.XboxKeyControl"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <UserControl.Resources>
        <SolidColorBrush x:Key="FeatureButtonBrush" Color="#e0e0e0" />
        <SolidColorBrush x:Key="XboxBlueBrush" Color="#11679E" />
        <SolidColorBrush x:Key="XboxGreenBrush" Color="#407C1B" />
        <SolidColorBrush x:Key="XboxRedBrush" Color="#E31123" />
        <SolidColorBrush x:Key="XboxYellowBrush" Color="#FEFE00" />
        <SolidColorBrush x:Key="XboxDarkYellowBrush" Color="#D8D800" />
        <x:String x:Key="GamepadViewPath">M15,13 L15,30 L38,30 L38,13 z M12,10 L15,10 L38,10 L41,10 L41,13 L41,30 L41,33 L38,33 L15,33 L12,33 L12,30 L12,13 z M0,0 L3,0 L29,0 L29,2 L29,7 L26,7 L26,3 L3,3 L3,20 L9,20 L9,23 L3,23 L0,23 L0,3 z</x:String>
        <x:String x:Key="MenuPath">M0,0 L0,1 L6,1 L6,0 z M0,2.5 L0,3.5 L6,3.5 L6,2.5 z M0,5 L0,6 L6,6 L6,5 z</x:String>
        <x:String x:Key="PlayButton">M0,0 L0,2 L1.5,1 z</x:String>
    </UserControl.Resources>
    <Grid>
        <Ellipse x:Name="CircleBackground" Height="26" Width="26" Fill="{StaticResource XboxBlueBrush}" />
        <TextBlock x:Name="Label" Foreground="White" FontWeight="SemiBold"
                   FontSize="16" Margin="0,-1.5,0,0" VerticalAlignment="Center" HorizontalAlignment="Center" />
        <Path x:Name="ViewPath"
              Stretch="Uniform" Width="14"
              Fill="{StaticResource FeatureButtonBrush}" Visibility="Collapsed" Data="{StaticResource GamepadViewPath}" />
        <Path x:Name="PlayPath"
              Stretch="Uniform" Width="10"
              Fill="{StaticResource FeatureButtonBrush}" Visibility="Collapsed" Margin="2,0,0,0" Data="{StaticResource PlayButton}" />
        <Path x:Name="MenuPath"
              Stretch="Uniform" Width="11"
              Fill="{StaticResource FeatureButtonBrush}" Visibility="Collapsed" Data="{StaticResource MenuPath}" />
    </Grid>
</UserControl>

and the corresponding c# file.

using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;


namespace Huyn.Controls
{

    public sealed partial class XboxKeyControl : UserControl
    {
        public enum Key { Unknown, X, Y, A, B, View, Play, Menu}

        private Key _currentKey = Key.Unknown;

        public XboxKeyControl()
        {
            InitializeComponent();
        }

        #region Symbol

        public Key Symbol
        {
            get => (Key)GetValue(SymbolProperty);
            set => SetValue(SymbolProperty, value);
        }

        // Using a DependencyProperty as the backing store for Symbol.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SymbolProperty =
            DependencyProperty.Register("Symbol", typeof(Key), typeof(XboxKeyControl), new PropertyMetadata(Key.Unknown, SymbolCallback));

        private static void SymbolCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((XboxKeyControl)d).UpdateButton();
        }

        #endregion



        private void Instance_IsMediaRemoteLastUsedChanged(object sender, bool e)
        {
            UpdateButton();
        }


        private void UpdateButton()
        {

            var symbol = Symbol;
            if (_currentKey == symbol)
                return;

            _currentKey = symbol;
            switch (symbol)
            {
                case Key.Unknown:
                    CircleBackground.Fill = null;
                    Label.Text = "";
                    Label.Visibility = Visibility.Collapsed;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Collapsed;
                    break;
                case Key.A:
                    CircleBackground.Fill = (Brush)Resources["XboxGreenBrush"];
                    Label.Text = "A";
                    Label.Visibility = Visibility.Visible;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Collapsed;

                    break;
                case Key.B:
                    CircleBackground.Fill = (Brush)Resources["XboxRedBrush"];
                    Label.Text = "B";
                    Label.Visibility = Visibility.Visible;
                    ViewPath.Visibility = Visibility.Collapsed;
                    break;
                case Key.X:
                    CircleBackground.Fill = (Brush)Resources["XboxBlueBrush"];
                    Label.Text = "X";
                    Label.Visibility = Visibility.Visible;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Collapsed;

                    break;
                case Key.Y:
                    CircleBackground.Fill = (Brush)Resources["XboxDarkYellowBrush"];
                    Label.Text = "Y";
                    Label.Visibility = Visibility.Visible;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Collapsed;

                    break;
                case Key.View:
                    CircleBackground.Fill = new SolidColorBrush(Colors.Black);
                    Label.Visibility = Visibility.Collapsed;
                    ViewPath.Visibility = Visibility.Visible;
                    PlayPath.Visibility = Visibility.Collapsed;
                    MenuPath.Visibility = Visibility.Collapsed;
                    break;
                case Key.Play:
                    CircleBackground.Fill = new SolidColorBrush(Colors.Black);
                    Label.Visibility = Visibility.Collapsed;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Visible;
                    MenuPath.Visibility = Visibility.Collapsed;
                    break;
                case Key.Menu:
                    CircleBackground.Fill = new SolidColorBrush(Colors.Black);
                    Label.Visibility = Visibility.Collapsed;
                    ViewPath.Visibility = Visibility.Collapsed;
                    PlayPath.Visibility = Visibility.Collapsed;
                    MenuPath.Visibility = Visibility.Visible;
                    break;
            }
        }


    }
}

 

Sample + Source

XboxKeyControllerDemo

Comments are closed.