In a previous post, we looked at how you could set platform specific values with the Device.OnPlatform<T> static method. Today we will see how we can achieve the same result by using the <OnPlatform> markup in a XAML file.

The problem we were facing was that some extra padding was required at the top for a single-page application, but only on iOS. We ended up with the following code in the code behind file:

Padding = new Thickness(0, Device.OnPlatform(iOS: 20, Android: 0, WinPhone: 0), 0, 0);

We can express a similar code in XAML markup only! The XAML version would look something like that:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Design2Code.MainPage">
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness">
      <OnPlatform.iOS>0,20,0,0</OnPlatform.iOS>
      <OnPlatform.Android>0,0,0,0</OnPlatform.Android>
      <OnPlatform.WinPhone>0,0,0,0</OnPlatform.WinPhone>
    </OnPlatform>
  </ContentPage.Padding>
    ...
</ContentPage>      

So what’s going on here? The Device.OnPlatform<T> method is in a generic method. While the generic type was implicitly defined in the code version based on the context, this is not possible in XAML and it needs to be defined explicitly. The x:TypeArguments attributes is available for that purpose. We assigned it the type Thickness which is the type of the Padding property. Then we can define for each platform the instance of Thickness that will be created.

Now there is a little trick that we can use to simplify the code even more. Since the default values for padding are the one for Android and WinPhone, we can remove these entries from the XAML file.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Design2Code.MainPage">
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness">
      <OnPlatform.iOS>0,20,0,0</OnPlatform.iOS>
    </OnPlatform>
  </ContentPage.Padding>
    ...
</ContentPage>      

Lastly, because the property Thickness can be represented by a single string, we can even define the property as an attribute like so

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="Design2Code.MainPage">
  <ContentPage.Padding>
    <OnPlatform x:TypeArguments="Thickness" iOS="0,20,0,0"/>
  </ContentPage.Padding>
    ...
</ContentPage>      

The final version is clear and precise.

What do you use? Do you prefer the C# or the XAML way of specifying UI properties for specific platforms?