Introduction to Adaptive UIs in UWP
Universal Windows Platform (UWP) allows developers to create one app that runs on multiple Windows devices, including desktops, tablets, phones, Xbox, HoloLens, and IoT devices. A key challenge is creating adaptive user interfaces that look good across different screen sizes and resolutions.
Microsoft provides state triggers, like AdaptiveTrigger, to simplify building adaptive UIs in XAML without writing additional C# code.
Understanding AdaptiveTrigger
AdaptiveTrigger has two main properties:
-
MinWindowWidth – The minimum window width at which the trigger activates
-
MinWindowHeight – The minimum window height at which the trigger activates
You use AdaptiveTrigger in combination with the Visual State Manager to adapt layouts based on screen or window size. For example, a horizontal layout on a desktop can switch to a vertical layout on a phone.
Example: Changing Background Color Based on Window Width
<VisualStateGroup x:Name=“WindowStates”>
<VisualState x:Name=“WideState”>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth=“800” />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target=“LayoutRoot.Background” Value=“LightYellow” />
</VisualState.Setters>
</VisualState>
<VisualState x:Name=“NarrowState”>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth=“0” />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target=“LayoutRoot.Background” Value=“LightGreen” />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
-
Background becomes light yellow for widths ≥ 800px
-
Background becomes light green for narrower widths
This works in real-time as you resize the window.
Practical Example: Adaptive Recipe App
In this example, the AdaptiveTriggerDemo app uses three StackPanels for recipe image, ingredients, and directions. The panels adapt based on window width:
-
Wide layout: Panels appear side-by-side
-
Narrow layout: Panels stack vertically
XAML Snippet for Layout Adaptation
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth=“800” />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target=“IngredientsPanel.(Grid.Row)” Value=“0” />
<Setter Target=“IngredientsPanel.(Grid.Column)” Value=“1” />
<Setter Target=“DirectionsPanel.(Grid.Row)” Value=“0” />
<Setter Target=“DirectionsPanel.(Grid.Column)” Value=“2” />
<Setter Target=“ImagePanel.(Grid.ColumnSpan)” Value=“1” />
</VisualState.Setters>
</VisualState>
<VisualState x:Name=“NarrowState”>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth=“0” />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target=“IngredientsPanel.(Grid.Row)” Value=“1” />
<Setter Target=“DirectionsPanel.(Grid.Row)” Value=“2” />
<Setter Target=“ImagePanel.(Grid.ColumnSpan)” Value=“3” />
</VisualState.Setters>
</VisualState>
-
Attached properties (Grid.Row, Grid.Column) use parentheses in setters
-
Multiple setters allow full layout adaptation per visual state
Tips for Building Adaptive UIs
-
Use one XAML file with VisualStateManager for multiple device sizes
-
Combine AdaptiveTrigger with custom triggers for advanced scenarios
-
Test layouts on multiple window sizes or devices
-
Use ScrollViewer when content may overflow on smaller screens
Extending AdaptiveTrigger
AdaptiveTrigger is the built-in trigger in UWP, but you can create custom state triggers for advanced layout scenarios. Examples and templates are widely available on GitHub.