我有一个用户界面,可以使用AdaptiveTrigger
来适应不同的设备外形。特别是,我有一个基于SplitView
的shell菜单,当最小窗口宽度分别为1000 epx和600 epx时,有两个状态触发器。 600 epx状态触发器可以在横向模式下触发某些移动设备,具体取决于其外形和比例因子,这是预期的行为。
但是,我注意到在桌面上,600 epx状态触发器在后台触发(从ShellSplitView.DisplayMode
更改为Overlay
到CompactOverlay
)主题设置,例如在暗和亮模式之间切换,改变强调色或切换高对比度模式;在移动模拟器和设备上,当我转到“设置”应用,更改主题设置并返回到我的应用时,它会触发。最特别的是,这只发生在默认状态,并且只有在我通过调整桌面上的窗口大小或通过旋转移动仿真器或设备来触发任何状态触发器之后才会发生。返回应用程序后再次调整大小/旋转会使问题消失。我以前没有在任何其他应用程序中看到过这种情况,包括Microsoft的应用程序或任何第三方UWP应用程序。
我已经确认这不是由其他一些干扰状态触发器的代码引起的,通过在一个空白的UWP项目中成功地再现问题,只有一个页面只包含SplitView
的任何数字视觉状态(和一些文本内容):
<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>
您可以尝试通过创建空白UWP项目,用上述XAML替换MainPage.xaml的内容并运行项目来自己重现问题。
考虑到我所做的一切都是改变主题设置,我不明白为什么会触发任何状态触发器。实际上,根据MSDN上的this guide,SplitView
元素属性中反映的默认值应自动重新应用:
使用状态触发器时,您不需要定义空的
DefaultState
。当不再满足状态触发条件时,将自动重新应用默认设置。
根据Windows.UI.Xaml.AdaptiveTrigger
page本身:
默认情况下,
StackPanel
方向为Vertical
。当窗口宽度> = 720有效像素时,会触发VisualState
更改,StackPanel
方向更改为Horizontal
。
...这一点,加强了我的观点 - 当我更改主题设置时,窗口宽度不会改变,所以我不明白为什么状态触发器会在不应该启动时启动,以及为什么只有在我通过调整窗口大小或旋转设备来触发状态更改之后。
为什么会发生这种情况,我该如何解决?
答案 0 :(得分:4)
此问题似乎已在所有设备系列的Windows 10周年更新中得到修复。当状态触发器不应该再激活时,状态触发器将不再激活,并且现在可以正确地重新应用状态触发器的指定外部的默认值。
如果您的应用仅在1607分支机构(构建 14393 )或更新版本上运行,则不需要此解决方法。请注意,这是指项目属性中指定的最低版本,不是目标版本。
如果您的应用将在1511分支(构建 10586 )或1507分支(构建 10240 >),即使它在具有较新版本的设备上表现正常。
不幸的是,我还没有能够解决这个问题而无需向VisualStateGroup
添加默认状态,使用最小尺寸为0 epx的状态触发器(您不需要任何setters - 你只需要一个状态触发器):
<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>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
至于为什么会发生这种情况,我的猜测是VisualStateManager
正在尝试进入更新系统主题的状态,但因为没有为初始定义(或&#34;默认&# 34;或&#34;正常&#34;)状态,它必须选择下一个最佳替代方案。我仍然不理解的是,VisualStateManager
首先更新系统主题时必须更改视觉状态的原因...不要{{{ 1}}自己刷新?他们为什么要依赖ThemeResource
?
值得注意的是,UWP中大多数关于自适应触发器的第三方教程已经这样做了。目前尚不清楚作者是否意识到这个问题,或者他们是否添加了默认状态只是因为他们习惯于在Silverlight / WPF时代这样做。但是,基于上面的文档和其他正确的UWP行为,这可能是一个边缘情况。