当我更改主题设置时,为什么我的AdaptiveTrigger会触发?

Bol*_*ock 7 xaml visualstatemanager windows-store-apps windows-10 uwp

我有一个用户界面,适应不同的设备形状因素使用AdaptiveTrigger.特别是,SplitView当最小窗口宽度分别为1000 epx和600 epx时,我有一个带有两个状态触发器的基于shell的菜单.600 epx状态触发器可以在横向模式下触发某些移动设备,具体取决于它们的形状因子和比例因子,这是预期的行为.

但是,我注意到在桌面上,一旦我改变主题设置,例如在暗和亮模式之间切换,改变强调颜色或切换高,600 epx状态触发器在后台触发(ShellSplitView.DisplayMode从更改OverlayCompactOverlay)对比模式; 在移动模拟器和设备上,当我转到"设置"应用,更改主题设置并返回到我的应用时,它会触发.最奇怪的是,这只发生在默认状态,并且只有在我通过调整桌面上的窗口大小或通过旋转移动仿真器或设备来触发任何状态触发器之后.返回应用程序后再次调整大小/旋转会使问题消失.我以前没有见过这种在任何其他应用程序,包括微软的应用程序或任何第三方应用程序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>
Run Code Online (Sandbox Code Playgroud)

您可以尝试通过创建空白UWP项目,用上述XAML替换MainPage.xaml的内容并运行项目来自己重现问题.

考虑到我所做的只是更改主题设置,我不明白为什么任何状态触发器会触发.实际上,根据MSDN 上的本指南,SplitView应该自动重新应用元素属性中反映的默认值:

使用状态触发器时,无需定义空DefaultState.当不再满足状态触发条件时,将自动重新应用默认设置.

并根据Windows.UI.Xaml.AdaptiveTrigger页面本身:

默认情况下,StackPanel方向是Vertical.当窗口宽度> = 720有效像素时,VisualState触发更改,并将StackPanel方向更改为Horizontal.

...这一点,加强了我的观点 - 当我改变主题设置时,窗口宽度不会改变,所以我不明白为什么状态触发器会在它不应该启动时启动,为什么只有在我之后通过调整窗口大小或旋转设备来触发状态更改.

那么为什么会发生这种情况,我该如何解决呢?

Bol*_*ock 4

此问题似乎已在所有设备系列的 Windows 10 周年更新中得到修复。状态触发器在不应该激活时将不再激活,并且现在可以正确地重新应用状态触发器外部指定的默认值。

\n\n
    \n
  • 如果您的应用程序仅在 1607 分支(内部版本14393 )或更新版本上运行,则不需要此解决方法。请注意,这指的是项目属性中指定的最低版本,而不是目标版本。

  • \n
  • 如果您的应用程序将在 1511 分支(内部版本10586)或 1507 分支(内部版本10240)上运行,则需要此解决方法,即使它在具有较新版本的设备上可以正常运行。

  • \n
\n\n
\n\n

不幸的是,如果不添加默认状态,我就无法解决这个问题VisualStateGroup,除非使用最小尺寸为 0 epx 的状态触发器添加默认状态(您不需要任何设置器 \xe2\x80\x94 你只需需要状态触发器):

\n\n
<VisualStateManager.VisualStateGroups>\n    <VisualStateGroup>\n        <VisualState>\n            <VisualState.StateTriggers>\n                <AdaptiveTrigger MinWindowWidth="1000"/>\n            </VisualState.StateTriggers>\n            <VisualState.Setters>\n                <Setter Target="ShellSplitView.DisplayMode" Value="Inline"/>\n                <Setter Target="ShellSplitView.IsPaneOpen" Value="True"/>\n            </VisualState.Setters>\n        </VisualState>\n        <VisualState>\n            <VisualState.StateTriggers>\n                <AdaptiveTrigger MinWindowWidth="600"/>\n            </VisualState.StateTriggers>\n            <VisualState.Setters>\n                <Setter Target="ShellSplitView.DisplayMode" Value="CompactOverlay"/>\n            </VisualState.Setters>\n        </VisualState>\n        <VisualState>\n            <VisualState.StateTriggers>\n                <AdaptiveTrigger MinWindowWidth="0"/>\n            </VisualState.StateTriggers>\n        </VisualState>\n    </VisualStateGroup>\n</VisualStateManager.VisualStateGroups>\n
Run Code Online (Sandbox Code Playgroud)\n\n

至于为什么会发生这种情况,我的猜测是,VisualStateManager当系统主题更新时,它试图进入一个状态,但由于没有为初始(或“默认”或“正常”)状态定义任何状态,所以它必须选择下一个最佳选择。我仍然不明白,为什么VisualStateManager当系统主题更新时必须改变视觉状态......不ThemeResource自己刷新?为什么他们要依赖VisualStateManager

\n\n

有趣的是,大多数有关 UWP 中自适应触发器的第三方教程已经做到了这一点。目前尚不清楚作者是否意识到了这个问题,或者他们添加默认状态是否只是因为他们在 Silverlight/WPF 时代就习惯了这样做。不过,根据上述文档和其他正确的 UWP 行为,这可能是一种边缘情况。

\n