This is the accompanying Gist to the blog post at cayas.de.
The OnOrientation
MarkupExtension helps to make XAML pages automatically adapt to orientation changes.
By enabling developers to provide different values for their view's properties directly inline in XAML, similiar to other MarkupExtensions like OnPlatform
and OnIdiom
.
For example it can be used to rearrange a Grid's ColumnDefinitions
to accommodate for orientation changes:
<Grid ColumnDefinitions="{OnOrientation Default='*', Landscape='*,*', TypeConverter={x:Type ColumnDefinitionCollectionTypeConverter}}">
(Why ColumnDefinitionCollectionTypeConverter needs to be specified here is explained below or in the blog post)
- Install
CommunityToolkit.Maui
into the project - Add
UseMauiCommunityToolkit()
toMauiProgram.cs
when configuring theMauiAppBuilder
- Add both classes,
OnOrientationExtension.cs
andOnOrientationSource.cs
, to the .NET MAUI project - Add the namespace alias to the XAML file
- Use
OnOrientation
either inline as MarkupExtension in attribute syntax, or via property element syntax
Make sure to always specify a value for Default
.
<Label Grid.Row="{OnOrientation Default=0, Landscape=1}" />
Since the values you provide in a MarkupExtension
must be of a primitive type like int
or string
and type conversion using TypeConverters does not kick in, sometimes you may need to use x:Static
.
<Label HorizontalOptions="{OnOrientation Default={x:Static LayoutOptions.Start}, Landscape={x:Static LayoutOptions.Center}}" />
If the value is more complex and you know which TypeConverter
should be used, you can specify it.
OnOrientation
can then perform type conversion using the provided Type of TypeConverter.
<Grid ColumnDefinitions="{OnOrientation Default='*', Landscape='*,*', TypeConverter={x:Type ColumnDefinitionCollectionTypeConverter}}">
When a complex value is needed and no TypeConverter exists, then you can also use property element syntax to specify the different values. Although one can argue that this is way too verbose for practical use.
<Grid.ColumnDefinitions>
<ext:OnOrientation>
<ext:OnOrientation.Default>
<ColumnDefinitionCollection>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="0" />
</ColumnDefinitionCollection>
</ext:OnOrientation.Default>
<ext:OnOrientation.Landscape>
<ColumnDefinitionCollection>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</ColumnDefinitionCollection>
</ext:OnOrientation.Landscape>
</ext:OnOrientation>
</Grid.ColumnDefinitions>
This syntax could also be used to switch out entire views.
<ContentView>
<ContentView.Content>
<ext:OnOrientation>
<Label Text="This text is visible in Default" />
<ext:OnOrientation.Landscape>
<Label Text="This text is visible in Landscape" />
</ext:OnOrientation.Landscape>
</ext:OnOrientation>
</ContentView.Content>
</ContentView>
- Only works with Android and iOS, since OnOrientationExtension uses the Orientation provided by DeviceDisplay.MainDisplayInfo.Orientation
- Value cannot be a BindingExpression