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

前端之家收集整理的这篇文章主要介绍了xaml – 当我更改主题设置时,为什么我的AdaptiveTrigger会触发?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个用户界面,可以使用AdaptiveTrigger适应不同的设备外形.特别是,我有一个基于SplitView的 shell菜单,当最小窗口宽度分别为1000 epx和600 epx时,它有两个状态触发器. 600 epx状态触发器可以在横向模式下触发某些移动设备,具体取决于其外形和比例因子,这是预期的行为.

但是,我注意到在桌面上,600 epx状态触发器在后台触发(将ShellSplitView.DisplayMode从Overlay更改为CompactOverlay),只要我更改主题设置,例如在暗和亮模式之间切换,更改重音颜色,或切换高对比度模式;在移动模拟器和设备上,当我转到“设置”应用,更改主题设置并返回到我的应用时,它会触发.最奇特的是,这只发生在默认状态,并且只有在我通过调整桌面上的窗口大小或通过旋转移动仿真器或设备来触发任何状态触发器之后才会发生.返回应用程序后再次调整大小/旋转会使问题消失.我以前没有在任何其他应用程序中看到过这种情况,包括微软的应用程序或任何第三方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元素属性中反映的默认值:

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.

根据Windows.UI.Xaml.AdaptiveTrigger page本身:

By default,the StackPanel orientation is Vertical. When the window width is >= 720 effective pixels,the VisualState change is triggered,and the StackPanel orientation is changed to Horizontal.

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

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

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

>如果您的应用程序仅在1607分支(build 14393)或更新版本上运行,则不需要此解决方法.请注意,这是指项目属性中指定的最小版本,而不是目标版本.
>如果您的应用程序将在1511分支(构建10586)或1507分支(构建10240)上运行,则需要此解决方法,即使它在具有较新构建的设备上运行正常.

不幸的是,我还没有能够解决这个问题而不仅仅是向VisualStateGroup添加一个默认状态,使用最小维度为0 epx的状态触发器(你不需要任何setter – 你只需要一个状态触发器) :

<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必须在系统主题首次更新时更改视觉状态…不要自己刷新ThemeResources?他们为什么要依赖VisualStateManager?

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

猜你在找的Windows相关文章