Skip to main content
Version: 11.0.x

Platform-Specific XAML

OnPlatform Markup Extension

Overview

The OnPlatform markup extension in Avalonia allows developers to specify different values for a property based on the operating system on which the application is running. This is particularly useful for creating cross-platform applications that need to adapt their UI or behavior according to the platform.

Basic usage in markup extension syntax

You can specify values for each platform and a default value that will be used if no specific platform match is found:

<TextBlock Text="{OnPlatform Default='Unknown', Windows='Im Windows', macOS='Im macOS', Linux='Im Linux'}"/>

Alternatively, you can use constructor syntax to define the default value directly, skipping Default keyword. Platform-specific properties still need to be defined:

<TextBlock Text="{OnPlatform 'Hello World', Android='Im Android'}"/>

You can use this markup extension with any other type, not only strings:

<Border Height="{OnPlatform 10, Windows=50.5}"/>

Specifying Type Arguments

You can use custom TypeArguments to explicitly specify the type for the values:

<TextBlock Tag="{OnPlatform '0, 0, 0, 0', Windows='10, 10, 10, 10', x:TypeArguments=Thickness}"/>

In this sample above, Tag property has type of object, so compiler doesn't have enough information to parse input strings. Without specifying TypeArguments, property will have value of string on all platforms. But since we have TypeArguments here, compiler will parse them as Thickness values.

Nested Markup Extensions

The OnPlatform extension supports nesting other markup extensions within it:

<Border Background="{OnPlatform Default={StaticResource DefaultBrush}, Windows={StaticResource WindowsBrush}}"/>

XML Syntax

OnPlatform can also be used in XML syntax for defining property values:

<StackPanel>
<OnPlatform>
<OnPlatform.Default>
<ToggleButton Content="Hello World" />
</OnPlatform.Default>
<OnPlatform.iOS>
<ToggleSwitch Content="Hello iOS" />
</OnPlatform.Windows>
</OnPlatform>
</StackPanel>

Note, in this sample, OnPlatform is a child of StackPanel. But in runtime only single actual control will be created (ToggleButton or ToggleSwitch) and added to the StackPanel.

Complex Property Setters

Similarly to the previous sample, OnPlatform can be part of complex property setters within a ResourceDictionary or other dictionaries or collections:

<ResourceDictionary>
<OnPlatform x:Key="MyBrush">
<OnPlatform.Default>
<SolidColorBrush Color="Blue" />
</OnPlatform.Default>
<OnPlatform.iOS>
<SolidColorBrush Color="Yellow" />
</OnPlatform.Windows>
</OnPlatform>
</ResourceDictionary>

XML Combining Syntax

To avoid branches duplication, it is possible to define multiple platforms in a single branch. Another useful example would be including platform-specific styles:

<Application.Styles>
<!-- Always included -->
<FluentTheme />

<!-- Only one branch is executed in runtime -->
<OnPlatform>
<!-- if (Android || iOS) -->
<On Options="Android, iOS">
<StyleInclude Source="/Styles/Mobile.axaml" />
</On>
<!-- else -->
<On Options="Default">
<StyleInclude Source="/Styles/Default.axaml" />
</On>
</OnPlatform>
</Application.Styles>

Additional details

OnPlatform markup extension works in a similar way to how switch-case works in C# code. Compiler will generate branches for all possible values, but only one branch will be executed at runtime depending on the condition.

It is also useful to remember that if an application is built with a specific Runtime Identifier and with Trimming Enabled, OnPlatform extension will have its branches trimmed only to those that are possible. For example, if OnPlatform had branches for Windows and macOS, but was built for Windows only, other branches will be removed, which also reduces application size.

OnFormFactor Markup Extension

The OnFormFactor markup extension functions similarly to the OnPlatform and has the same general syntax. The main difference is that it allows defining values not per platform, but per device form factor, such as Desktop and Mobile:

<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<TextBlock Text="{OnFormFactor 'Default value', Mobile='Im Mobile', Desktop='Im Desktop'}"/>
</UserControl>

OnFormFactor doesn't have any compile-time trimming optimizations, as form factor cannot be known in compile time. None of these markup extensions are dynamic; once a value is set, it will not be changed.