WinUI3自定义NavigationViewItem选中样式:悬停/按下时保持强调色
你当前的样式只设置了NavigationViewItem的默认状态属性,而悬停、按下这类交互状态的外观是由控件模板(ControlTemplate)内的VisualStateManager控制的,所以需要扩展样式,覆盖对应交互状态的视觉属性。
步骤1:修改XAML中的Style,覆盖控件模板的视觉状态
基于WinUI3默认的NavigationViewItem样式,修改sx1样式,添加控件模板并调整选中相关的交互状态(比如SelectedPointerOver、SelectedPressed)的背景和前景:
<NavigationView.Resources> <Style TargetType="NavigationViewItem" x:Key="sx1"> <!-- 基础状态属性 --> <Setter Property="Background" Value="{ThemeResource AccentTextFillColorPrimaryBrush}"/> <Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}"/> <!-- 重写控件模板,修改交互状态 --> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="NavigationViewItem"> <Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}" Control.IsTemplateFocusTarget="True"> <!-- 视觉状态管理 --> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="PointerStates"> <!-- 默认选中状态 --> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource AccentTextFillColorPrimaryBrush}"/> <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}"/> </VisualState.Setters> </VisualState> <!-- 选中+鼠标悬停状态 --> <VisualState x:Name="SelectedPointerOver"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource AccentTextFillColorPrimaryBrush}"/> <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}"/> </VisualState.Setters> </VisualState> <!-- 选中+鼠标按下状态 --> <VisualState x:Name="SelectedPressed"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource AccentTextFillColorPrimaryBrush}"/> <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}"/> </VisualState.Setters> </VisualState> <!-- 非选中状态(按需保留默认样式) --> <VisualState x:Name="Normal"/> <VisualState x:Name="PointerOver"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPointerOver}"/> <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundPointerOver}"/> </VisualState.Setters> </VisualState> <VisualState x:Name="Pressed"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPressed}"/> <Setter Target="ContentPresenter.Foreground" Value="{ThemeResource NavigationViewItemForegroundPressed}"/> </VisualState.Setters> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!-- 控件内容容器(保留默认布局结构) --> <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </NavigationView.Resources>
提示:实际开发中建议通过Blend工具提取WinUI3默认的
NavigationViewItem完整模板,再修改对应VisualState属性,避免丢失控件的默认布局和功能。
步骤2:确保C++/WinRT代码正确应用样式
你的现有代码中st0_def赋值为nullptr,若要应用默认样式可直接省略Style设置;应用sx1样式的代码无需修改,只需确保navView是正确的NavigationView实例:
winrt::Microsoft::UI::Xaml::Style st1_def = navView.Resources().Lookup(winrt::box_value(L"sx1")).as<winrt::Microsoft::UI::Xaml::Style>(); // 为item2应用自定义样式 navView.FindName(L"item2").as<winrt::Microsoft::UI::Xaml::Controls::NavigationViewItem>().Style(st1_def);
关键说明
- 必须为所有选中相关的交互状态(
Selected、SelectedPointerOver、SelectedPressed)设置相同的强调色属性,才能保证任意交互状态下样式一致。 - 使用系统主题资源(如
AccentTextFillColorPrimaryBrush、TextOnAccentFillColorPrimaryBrush)可让样式自动跟随系统主题变化。
内容的提问来源于stack exchange,提问作者Michael Chourdakis
相关产品推荐
相关产品推荐

