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

7
我有一个用户界面,使用AdaptiveTrigger适应不同的设备形态。特别地,我有一个基于SplitView的Shell菜单,具有两种状态触发器,分别在最小窗口宽度为1000 epx和600 epx时触发。在某些移动设备上,根据其形态和比例因素,横向模式下可以触发600 epx状态触发器,这是预期行为。
然而,我注意到在桌面上,只要我更改主题设置(如在深色和浅色模式之间切换、更改强调颜色或切换高对比度模式),就会在后台触发600 epx状态触发器(将ShellSplitView.DisplayModeOverlay更改为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 项目并将 MainPage.xaml 的内容替换为上述 XAML,然后运行该项目来尝试重现此问题。
考虑到我所做的一切都是更改主题设置,我不明白为什么任何状态触发器都会触发。实际上,根据 MSDN 上的此指南,应该自动重新应用在 SplitView 元素属性中反映的默认值:
当您使用状态触发器时,不需要定义一个空的 DefaultState。当不再满足状态触发器的条件时,会自动重新应用默认设置。
而且根据 Windows.UI.Xaml.AdaptiveTrigger 页面本身的说明:
默认情况下,StackPanel 方向为垂直。当窗口宽度>= 720 个有效像素时,会触发 VisualState 更改,StackPanel 方向会更改为水平。
这些信息共同强化了我的观点--当我更改主题设置时,窗口宽度并未发生变化,因此我不明白为什么状态触发器会在不应该的情况下触发,而且为什么只有在我调整窗口大小或旋转设备后才会触发状态更改。
那么这是为什么呢?如何解决?
1个回答

4
这个问题似乎在Windows 10周年更新中已经得到解决,适用于所有设备系列。当状态触发器不应该被激活时,状态触发器将不再激活,并且指定在状态触发器之外的默认值现在将被正确地重新应用。
  • 如果您的应用程序仅在1607分支(版本14393)或更新版本上运行,则不需要此解决方法。请注意,这是指您项目属性中指定的最小版本,而不是目标版本。

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


不幸的是,我无法绕过此问题,除非在VisualStateGroup中添加一个默认状态,使用一个最小尺寸为0 epx的状态触发器(您不需要任何设置器 - 只需要一个状态触发器):

<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试图在系统主题更新时切换到一个状态,但由于没有定义初始(或“默认”或“正常”)状态,它必须选择下一个最佳方案。我仍然不理解的是,为什么VisualStateManager首先需要在系统主题更新时更改视觉状态...难道ThemeResource不能自动刷新吗?为什么它们要依赖于VisualStateManager呢?
值得注意的是,在UWP中关于自适应触发器的大多数第三方教程已经这样做了。作者是否意识到了这个问题还是只是因为他们习惯了在Silverlight/WPF时代这样做而添加了默认状态,目前还不清楚。但根据上述文档和其他正确的UWP行为,这可能是一个边缘情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接