vendredi 4 mars 2016

Using an adaptive trigger to detect what platform your application is running on (Windows 10, XAML, C#)

I recently had issues with not knowing what platform my application was running on and wanted to have a specific UI depending on the platform and not depending on the size of the window.

Previously I had created a simple class (here) that allows you very simply detect what platform you are running on.  Next all I needed was to create a custom state trigger based on my previous class and we will be able to detect whether we are running on a Mobile, Tablet or Xbox platform.

First we need to create class that inherits from StateTriggerBase as follows:

namespace Win10.StateTriggers
{
    //you will also need https://gist.github.com/Delaire/37cbe07738df34bfd5e8
    public class DeviceFamilyStateTrigger : StateTriggerBase
    {
        private static DeviceTypeEnum deviceFamily;

        static DeviceFamilyStateTrigger()
        {
            deviceFamily = DeviceTypeHelper.GetDeviceType();
        }

        public DeviceTypeEnum DeviceFamily
        {
            get { return (DeviceTypeEnum)GetValue(DeviceFamilyProperty); }
            set { SetValue(DeviceFamilyProperty, value); }
        }

        public static readonly DependencyProperty DeviceFamilyProperty =
            DependencyProperty.Register("DeviceFamily", typeof(DeviceTypeEnum), typeof(DeviceFamilyStateTrigger),
            new PropertyMetadata(DeviceTypeEnum.Other, OnDeviceTypePropertyChanged));

        private static void OnDeviceTypePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var obj = (DeviceFamilyStateTrigger)d;
            var val = (DeviceTypeEnum)e.NewValue;

            if (deviceFamily == val)
                obj.IsActive = true;
        }

        private bool m_IsActive;

        public bool IsActive
        {
            get { return m_IsActive; }
            private set
            {
                if (m_IsActive != value)
                {
                    m_IsActive = value;
                    base.SetActive(value);
                    if (IsActiveChanged != null)
                        IsActiveChanged(this, EventArgs.Empty);
                }
            }
        }

        public event EventHandler IsActiveChanged;
    }   
}

what we have here is that we get the current platform type and check to see if our DeviceFamily property is of the same value, if so then the trigger will return an IsActive to true.

Here is how to use it in your XAML code: (the data in here is fake of course)

<VisualStateManager.VisualStateGroups>
   <VisualStateGroup x:Name="AbcVisualStateGroup">
      <VisualState x:Name="AbcVisualStateNarrow">
          <VisualState.StateTriggers>
     <AdaptiveTrigger x:Name="AbcVisualStateNarrowTrigger" MinWindowWidth="100" />
   </VisualState.StateTriggers>
   <VisualState.Setters>
     <Setter Target="AbcControl.(UIElement.Visibility)" Value="Collapsed" />
   </VisualState.Setters>
     </VisualState>
  <VisualState x:Name="AbcVisualStateNormal">
     <VisualState.StateTriggers>
       <AdaptiveTrigger x:Name="AbcVisualStateNormalTrigger" MinWindowWidth="400" />
       <stateTriggers:DeviceFamilyStateTrigger DeviceFamily="Xbox" />
         </VisualState.StateTriggers>
  <VisualState.Setters>
    <Setter Target="AbcControl.(UIElement.Visibility)" Value="Visible" />
 </VisualState.Setters>
      </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

What we can see here is that the state AbcVisualStateNormal will be called when we have MinWindowWidth="400"  or when DeviceFamily="Xbox". 

As you can see it was quite simple =)

Here are my 2 classes that you will need DeviceTypeHelper.cs and DeviceFamilyStateTrigger.cs


Happy coding!