如何让NavViewItem表现为Push Button而非Radio Button,选中后不保持按下状态?
要实现NavigationViewItem点击后不保持选中(按下)状态,和普通Push Button的行为一致,这里有两种实用方案,我给你详细拆解下:
方案一:自定义NavigationViewItem样式(推荐)
NavigationViewItem默认内部是用ToggleButton来实现选中状态的,我们可以修改它的模板,把ToggleButton替换成普通Button,从根源上移除Toggle的行为:
- 先提取默认的NavigationViewItem样式(可以用Blend工具导出,或者参考WinUI官方的基础样式代码)
- 找到模板里的
<ToggleButton>元素,将其替换为<Button>,并调整对应的样式绑定 - 移除或删除与Checked状态相关的视觉状态,只保留Button的Normal、PointerOver、Pressed等常规状态
这里给你一个简化后的样式示例,你可以直接用到项目里:
<Page.Resources> <Style x:Key="PushStyleNavViewItem" TargetType="NavigationViewItem"> <Setter Property="Foreground" Value="{ThemeResource NavigationViewItemForeground}"/> <Setter Property="Background" Value="{ThemeResource NavigationViewItemBackground}"/> <Setter Property="Padding" Value="12,0"/> <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="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="PointerOver"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPointerOver}"/> <Setter Target="ContentContainer.Foreground" Value="{ThemeResource NavigationViewItemForegroundPointerOver}"/> </VisualState.Setters> </VisualState> <VisualState x:Name="Pressed"> <VisualState.Setters> <Setter Target="LayoutRoot.Background" Value="{ThemeResource NavigationViewItemBackgroundPressed}"/> <Setter Target="ContentContainer.Foreground" Value="{ThemeResource NavigationViewItemForegroundPressed}"/> </VisualState.Setters> </VisualState> <!-- 移除所有Checked相关的视觉状态,彻底取消选中残留 --> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!-- 把原来的ToggleButton替换为普通Button --> <Button x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" Style="{StaticResource NavigationViewItemButtonStyle}"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </Page.Resources>
然后给你的NavigationViewItem应用这个样式:
<NavigationView x:Name="NavView"> <NavigationView.MenuItems> <NavigationViewItem Style="{StaticResource PushStyleNavViewItem}" Content="首页" Tag="HomePage"/> <NavigationViewItem Style="{StaticResource PushStyleNavViewItem}" Content="我的" Tag="ProfilePage"/> </NavigationView.MenuItems> </NavigationView>
这个方案的优势是视觉行为完全贴合Push Button,不会有任何选中残留,体验更流畅,适合长期使用。
方案二:在SelectionChanged事件中重置选中状态(快速实现)
如果你不想修改样式,也可以在导航完成后手动清除NavigationView的选中项,以此去掉按下状态:
修改你现有的SelectionChanged事件处理代码:
private void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { if (args.IsSettingsSelected) { NavView.Header = "设置"; rootFrame.Navigate(typeof(SettingsPage)); // 重置设置项的选中状态 sender.SelectedItem = null; } else if (args.SelectedItem != null) { NavigationViewItem item = args.SelectedItem as NavigationViewItem; NavView.Header = item.Tag.ToString(); // 执行你的导航逻辑 Type targetPage = Type.GetType(item.Tag.ToString()); if (targetPage != null) { rootFrame.Navigate(targetPage); } // 延迟重置选中项,避免和导航逻辑冲突 _ = Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low, () => { sender.SelectedItem = null; }); } }
这里用Dispatcher延迟重置,是为了确保导航操作已经完成,避免出现逻辑冲突。这个方案的好处是代码修改快,但可能会有短暂的选中视觉闪烁,适合快速验证需求。
内容的提问来源于stack exchange,提问作者Bimo
相关产品推荐
相关产品推荐

