You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让NavViewItem表现为Push Button而非Radio Button,选中后不保持按下状态?

让NavigationViewItem表现为Push Button而非Toggle Button

要实现NavigationViewItem点击后不保持选中(按下)状态,和普通Push Button的行为一致,这里有两种实用方案,我给你详细拆解下:

方案一:自定义NavigationViewItem样式(推荐)

NavigationViewItem默认内部是用ToggleButton来实现选中状态的,我们可以修改它的模板,把ToggleButton替换成普通Button,从根源上移除Toggle的行为:

  1. 先提取默认的NavigationViewItem样式(可以用Blend工具导出,或者参考WinUI官方的基础样式代码)
  2. 找到模板里的<ToggleButton>元素,将其替换为<Button>,并调整对应的样式绑定
  3. 移除或删除与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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:13:10