【问题标题】:Using Visual State Manager on a Style based on another Style在基于另一种样式的样式上使用视觉状态管理器
【发布时间】:2018-10-09 16:29:34
【问题描述】:

我在用 xaml 编写、理解可视状态管理器和使用样式方面遇到了很多困难。

我一直在创建一个 UWP 应用,并且主要使用 C# 来开发我的 UI。但是,我想改用 xaml,但对标记语言缺乏经验。

我想要实现的,我一生都想不通的,是创建基于具有附加状态的“父”样式的样式,主要是为了改变可见性。

这是一个示例,我创建了一个名为“NavigationViewItemStyle”的默认样式的实例。然后我有一些基于 NavigationViewItemStyle 的样式。我想要做的是添加可以在 C# 中触发的其他状态以更改控件的可见性。

下面是我的默认样式...只是一个简单的副本

      <Style x:Key="NavigationViewItemStyle" TargetType="NavigationViewItem">
            <Setter Property="Foreground" Value="{ThemeResource NavigationViewItemForeground}"/>
            <Setter Property="Background" Value="{ThemeResource NavigationViewItemBackground}"/>
            <Setter Property="BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrush}"/>
            <Setter Property="BorderThickness" Value="{StaticResource NavigationViewItemBorderThickness}"/>
            <Setter Property="UseSystemFocusVisuals" Value="True"/>
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="NavigationViewItem">
                        <Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Height="40" Control.IsTemplateFocusTarget="True">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="PointerStates">
                                    <VisualState x:Name="Normal"/>
                                    <VisualState x:Name="PointerOver">
                                        <VisualState.Setters>
                                            <Setter Target="LayoutRoot.(RevealBrush.State)" Value="PointerOver"/>
                                            <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPointerOver}"/>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushPointerOver}"/>
                                            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundPointerOver}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <VisualState.Setters>
                                            <Setter Target="LayoutRoot.(RevealBrush.State)" Value="Pressed"/>
                                            <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPressed}"/>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushPressed}"/>
                                            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundPressed}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState x:Name="Selected">
                                        <VisualState.Setters>
                                            <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundSelected}"/>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushSelected}"/>
                                            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundSelected}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState x:Name="PointerOverSelected">
                                        <VisualState.Setters>
                                            <Setter Target="LayoutRoot.(RevealBrush.State)" Value="PointerOver"/>
                                            <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundSelectedPointerOver}"/>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushSelectedPointerOver}"/>
                                            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundSelectedPointerOver}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState x:Name="PressedSelected">
                                        <VisualState.Setters>
                                            <Setter Target="LayoutRoot.(RevealBrush.State)" Value="Pressed"/>
                                            <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundSelectedPressed}"/>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushSelectedPressed}"/>
                                            <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundSelectedPressed}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="DisabledStates">
                                    <VisualState x:Name="Enabled"/>
                                    <VisualState x:Name="Disabled">
                                        <VisualState.Setters>
                                            <Setter Target="RevealBorder.BorderBrush" Value="{ThemeResource NavigationViewItemBorderBrushCheckedDisabled}"/>
                                            <Setter Target="LayoutRoot.Opacity" Value="{ThemeResource ListViewItemDisabledThemeOpacity}"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                                <VisualStateGroup x:Name="IconStates">
                                    <VisualState x:Name="IconVisible"/>
                                    <VisualState x:Name="IconCollapsed">
                                        <VisualState.Setters>
                                            <Setter Target="IconBox.Visibility" Value="Collapsed"/>
                                            <Setter Target="IconColumn.Width" Value="16"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Grid HorizontalAlignment="Left" VerticalAlignment="Center">
                                <Rectangle x:Name="SelectionIndicator" Fill="{ThemeResource NavigationViewSelectionIndicatorForeground}" Height="24" Opacity="0.0" Width="6"/>
                            </Grid>
                            <Border x:Name="RevealBorder" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
                            <Grid x:Name="ContentGrid" HorizontalAlignment="Left" Height="40">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition x:Name="IconColumn" Width="48"/>
                                    <ColumnDefinition Width="*"/>
                                </Grid.ColumnDefinitions>
                                <ToolTipService.ToolTip>
                                    <ToolTip x:Name="ToolTip"/>
                                </ToolTipService.ToolTip>
                                <Viewbox x:Name="IconBox" Child="{TemplateBinding Icon}" Margin="16,12"/>
                                <ContentPresenter x:Name="ContentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentTransitions="{TemplateBinding ContentTransitions}" Grid.Column="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

然后我根据我的默认样式创建了自定义样式

<Style x:Key="HomeNavigationViewItemStyle" TargetType="NavigationViewItem" BasedOn="{StaticResource NavigationViewItemStyle}">
</Style>

我无法解决的是如何在自定义样式中包含其他状态以更改控件的可见性。

即我有 4 种不同的应用程序可以处于的状态,并且根据状态,某些导航视图项是可见的或折叠的。

为了让事情变得简单,我想要

<VisualStateGroup x:Name="NavigationViewStates">
    <VisualState x:Name="NavigationViewState1">
        <VisualState.Setters>
            <Setter Target="Visibility" Value="Visible"/>
        </VisualState.Setters>
    </VisualState>
    <VisualState x:Name="NavigationViewState2">
        <VisualState.Setters>
            <Setter Target="Visibility" Value="Collapsed"/>
        </VisualState.Setters>
    </VisualState>
    <VisualState x:Name="NavigationViewState3">
        <VisualState.Setters>
            <Setter Target="Visibility" Value="Collapsed"/>
        </VisualState.Setters>
    </VisualState>
</VisualStateGroup>

但不知道如何让它工作....

任何人都可以帮助我或引导我朝着正确的方向前进吗?

【问题讨论】:

  • VisualStateGroup 应在 XAML 中声明为控件模板的一部分。你想如何触发这些视觉状态?在什么条件下?
  • 感谢您的回复,是的,这是我在“基本”样式中遇到困难的地方,我在控件模板上附加了一个 VisualStateGroup。在我的“子”样式中,我尝试将第二个 VisualStateGroup 附加到有点独立的控件模板(即,可以结合“子”视觉状态触发“基本”视觉状态组中的视觉状态)。我想通过代码触发我的“子”视觉状态(即 visualstatemanager.gotostate(item1, "NavigationViewState1")
  • 我想知道你想在什么条件下触发这些视觉状态。例如,在什么条件下,您要触发 'NavigationViewState1'?
  • 我的导航窗格中有一个带有 3 个 appbartoggle 按钮的命令栏。更改 appbartogglebutton 处于活动状态(即打开 appbartogglebutton 将关闭其他 2 个)将更改导航窗格内容的视觉状态。
  • 那么,您是否想通过appbartogglebutton的状态显示/隐藏NavigationView中的所有NavigationViewItems?

标签: c# xaml uwp


【解决方案1】:

根据附加的样式,项目将可见或折叠

有一种简单的方法可以实现您的目标。你可以使用NavigationView.MenuItemContainerStyleSelector Property。您需要制作自定义样式选择器来为 NavigationViewItem 应用不同的样式,并且在代码隐藏(自定义样式选择器类)中,您可以根据项目显示/隐藏 NavigationViewItem。这样就不需要使用视觉状态了。

参考以下代码:

<Page.Resources>
    <Style x:Key="s1" TargetType="NavigationViewItem">
        <Setter Property="Visibility" Value="Visible"></Setter>
    </Style>
    <Style x:Key="s2" TargetType="NavigationViewItem">
        <Setter Property="Visibility" Value="Collapsed"></Setter>
    </Style>
    <Style x:Key="s3" TargetType="NavigationViewItem">
        <Setter Property="Visibility" Value="Visible"></Setter>
    </Style>
    <local:CustomStyleSelector x:Key="customStyleSelector" style1="{StaticResource s1}" style2="{StaticResource s2}" style3="{StaticResource s3}"></local:CustomStyleSelector>
</Page.Resources>

<Grid>
    <NavigationView x:Name="NavView"
                IsSettingsVisible="True"
                Header="Welcome" MenuItemContainerStyleSelector="{StaticResource customStyleSelector}">
        <NavigationView.MenuItems>
            <NavigationViewItem Content="Home" x:Name="home" Tag="home">
                <NavigationViewItem.Icon>
                    <FontIcon Glyph="&#xE10F;"/>
                </NavigationViewItem.Icon>
            </NavigationViewItem>
            <NavigationViewItem Icon="AllApps" Content="item1" x:Name="apps" Tag="apps"/>
            <NavigationViewItem Icon="Video" Content="item2" x:Name="games" Tag="games"/>
            <NavigationViewItem Icon="Audio" Content="item3" x:Name="music" Tag="music"/>
        </NavigationView.MenuItems>
    </NavigationView>
</Grid>
public class CustomStyleSelector: StyleSelector
{
    public Style style1 { get; set; }
    public Style style2 { get; set; }
    public Style style3 { get; set; }
    protected override Style SelectStyleCore(object item, DependencyObject container)
    {
        if (item is NavigationViewItem)
        {
            if ((item as NavigationViewItem).Content.ToString() == "item1")
            {
                return style1;
            }
            if ((item as NavigationViewItem).Content.ToString() == "item2")
            {
                return style2;
            }
            if ((item as NavigationViewItem).Content.ToString() == "item3")
            {
                return style3;
            }
        }
        return base.SelectStyleCore(item, container);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 2013-08-06
    • 2011-08-06
    • 2016-06-01
    • 1970-01-01
    相关资源
    最近更新 更多