I have a user interface that adapts to different device form factors using AdaptiveTrigger
. In particular, I have a SplitView
-based shell menu with two state triggers for when the minimum window width is 1000 epx and 600 epx respectively. The 600 epx state trigger can fire on certain mobile devices in landscape mode depending on their form factor and scale factor, and this is intended behavior.
However, I've noticed that on the desktop, the 600 epx state trigger fires in the background (changing ShellSplitView.DisplayMode
from Overlay
to CompactOverlay
) as soon as I change a theme setting such as toggling between dark and light mode, changing the accent color, or toggling high contrast mode; and on both the mobile emulator and a device, it fires when I go to the Settings app, change a theme setting, and return to my app. Most peculiarly, this only happens in the default state and only after I've caused any of the state triggers to fire, by resizing the window on the desktop or by rotating the mobile emulator or device. Resizing/rotating again after returning to the app makes the problem go away. I have not previously seen this in any other apps, including Microsoft's apps or any third-party UWP apps.
I've confirmed that this is not caused by some other code interfering with the state triggers, by successfully reproducing the problem in a blank UWP project with a single page containing nothing but a SplitView
with any number of visual states (and some text content):
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1000"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ShellSplitView.DisplayMode" Value="Inline"/>
<Setter Target="ShellSplitView.IsPaneOpen" Value="True"/>
</VisualState.Setters>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="ShellSplitView.DisplayMode" Value="CompactOverlay"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SplitView
x:Name="ShellSplitView"
CompactPaneLength="48"
DisplayMode="Overlay"
IsPaneOpen="False"
OpenPaneLength="256">
<SplitView.Content>
<TextBlock Text="Content"/>
</SplitView.Content>
<SplitView.Pane>
<TextBlock Text="Pane"/>
</SplitView.Pane>
</SplitView>
</Grid>
</Page>
You can attempt to reproduce the problem yourself by creating a blank UWP project, replacing the contents of MainPage.xaml with the above XAML, and running the project.
Considering all I did was change the theme settings, I don't understand why any of the state triggers would fire. In fact, according to this guide on MSDN, the default values reflected in the SplitView
element's attributes should be reapplied automatically:
When you use state triggers, you don't need to define an empty
DefaultState
. The default settings are reapplied automatically when the conditions of the state trigger are no longer met.
And according to the Windows.UI.Xaml.AdaptiveTrigger
page itself:
By default, the
StackPanel
orientation isVertical
. When the window width is >= 720 effective pixels, theVisualState
change is triggered, and theStackPanel
orientation is changed toHorizontal
.
... which, together, reinforce my point — the window width does not change when I change the theme settings, so I don't see why the state trigger would kick in when it shouldn't, and why only after I've triggered a state change by resizing the window or rotating the device.
So why is this happening, and how do I fix it?