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

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

不过,我已经注意到,在桌面上,在600 EPX状态触发器触发的背景(改变ShellSplitView.DisplayModeOverlayCompactOverlay )只要我更改主题设置,如深色和浅色模式之间切换,改变口音颜色或切换高对比度模式; 并且在移动模拟器和设备上,当我转到“设置”应用,更改主题设置并返回到我的应用时,它会触发。 最奇怪的是,这只发生在默认状态下,并且只有通过调整桌面窗口大小或旋转移动模拟器或设备,才能触发任何状态触发器。 回到应用程序后再次调整大小/旋转使问题消失。 我以前从未在任何其他应用中看到过这一点,包括微软的应用或任何第三方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上的本指南, SplitView元素属性中反映的默认值应自动重新应用:

当你使用状态触发器时,你不需要定义一个空的DefaultState 。 当不再满足状态触发器的条件时,将自动重新应用默认设置。

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

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

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

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


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

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

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


  • 不幸的是,我还没有能够解决这个问题,而无需向VisualStateGroup添加默认状态,使用最小维数为0的状态触发器(您不需要任何设置器 - 您只需要一个状态触发器) :

    <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行为,这可能是一个边缘情况。

    链接地址: http://www.djcxy.com/p/91801.html

    上一篇: Why does my AdaptiveTrigger fire when I change the theme settings?

    下一篇: Toggle the display of a ul submenu only if parent li is clicked