WinUI 3嵌套标签导航实现咨询:NavigationView适配折叠模式
基于NavigationViewItem自定义控件的方案完全可行,而且是贴合你需求的最优方向之一。下面给两种简洁可复用的实现思路:
方案一:修改NavigationViewItem的ControlTemplate(原生适配,复用性强)
直接修改默认NavigationViewItem的模板,通过VisualState适配Pane的不同显示模式,无需额外自定义控件:
- 提取默认模板:使用Blend打开WinUI项目,右键NavigationViewItem -> 编辑模板 -> 编辑副本,生成默认ControlTemplate。
- 添加状态切换逻辑:在模板的
VisualStateManager中,针对NavigationViewPaneCompact和NavigationViewPaneExpanded状态,控制文本、下划线的显示:- 展开模式(Expanded):显示图标+文本,给选中项添加下划线(用
Border或Rectangle实现,绑定IsSelected属性控制可见性和样式) - 折叠模式(Compact):隐藏文本,仅保留图标,保持垂直布局
- 展开模式(Expanded):显示图标+文本,给选中项添加下划线(用
关键XAML代码片段:
<ControlTemplate TargetType="NavigationViewItem"> <!-- 保留原有模板基础结构 --> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="PaneDisplayModeStates"> <VisualState x:Name="NavigationViewPaneExpanded"> <VisualState.Setters> <Setter Target="ContentPresenter.Visibility" Value="Visible"/> <Setter Target="UnderlineBorder.Visibility" Value="Visible"/> </VisualState.Setters> </VisualState> <VisualState x:Name="NavigationViewPaneCompact"> <VisualState.Setters> <Setter Target="ContentPresenter.Visibility" Value="Collapsed"/> <Setter Target="UnderlineBorder.Visibility" Value="Collapsed"/> </VisualState.Setters> </VisualState> </VisualStateGroup> <VisualStateGroup x:Name="SelectionStates"> <VisualState x:Name="Selected"> <VisualState.Setters> <Setter Target="UnderlineBorder.Background" Value="{ThemeResource SystemAccentColor}"/> <!-- 可补充其他选中态样式,如文本颜色 --> </VisualState.Setters> </VisualState> <VisualState x:Name="Unselected"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <!-- 新增下划线元素,嵌入原有布局 --> <Grid> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <FontIcon x:Name="IconElement" Glyph="{TemplateBinding Icon}" Margin="0,0,8,0"/> <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}"/> </StackPanel> <Border x:Name="UnderlineBorder" Height="2" Margin="0,0,0,-2" VerticalAlignment="Bottom" Background="Transparent" Visibility="Collapsed"/> </Grid> </ControlTemplate>
- 全局应用模板:将修改后的模板放到
Application.Resources中,所有NavigationViewItem会自动应用该样式。
方案二:动态切换ContentTemplate(快速实现,灵活度高)
通过监听NavigationView的PaneDisplayModeChanged事件,给每个NavigationViewItem切换不同的内容模板:
- 定义两种DataTemplate:在XAML资源中分别定义展开和折叠模式的模板:
<Page.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/> <DataTemplate x:Key="ExpandedItemTemplate"> <StackPanel Orientation="Horizontal" VerticalAlignment="Center"> <FontIcon Glyph="{Binding Icon}"/> <TextBlock x:Name="TitleText" Text="{Binding Title}" Margin="8,0,0,0"/> <Border Height="2" Width="{Binding ActualWidth, ElementName=TitleText}" VerticalAlignment="Bottom" Background="{ThemeResource SystemAccentColor}" Visibility="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=NavigationViewItem}, Converter={StaticResource BooleanToVisibilityConverter}}"/> </StackPanel> </DataTemplate> <DataTemplate x:Key="CompactItemTemplate"> <FontIcon Glyph="{Binding Icon}" VerticalAlignment="Center"/> </DataTemplate> </Page.Resources>
- 绑定MenuItems数据源:用ViewModel绑定NavigationView的MenuItems,每个项包含
Icon、Title属性:
public class NavItemViewModel { public string Icon { get; set; } public string Title { get; set; } } // 后台初始化数据源 private void Page_Loaded(object sender, RoutedEventArgs e) { MainNav.MenuItemsSource = new List<NavItemViewModel> { new NavItemViewModel { Icon = "\uE80F", Title = "首页" }, new NavItemViewModel { Icon = "\uE81F", Title = "设置" }, new NavItemViewModel { Icon = "\uE82E", Title = "统计" } }; }
- 监听Pane模式变化:在后台代码中切换模板:
private void MainNav_PaneDisplayModeChanged(NavigationView sender, NavigationViewPaneDisplayModeChangedEventArgs args) { var targetTemplate = sender.PaneDisplayMode == NavigationViewPaneDisplayMode.Expanded ? Resources["ExpandedItemTemplate"] as DataTemplate : Resources["CompactItemTemplate"] as DataTemplate; foreach (var item in sender.MenuItems) { if (item is NavigationViewItem navItem) { navItem.ContentTemplate = targetTemplate; } } }
注意事项
- 方案一需兼容NavigationView的所有Pane模式(如Minimal),可按需添加对应的VisualState。
- 下划线样式可根据设计需求调整颜色、宽度、位置,建议绑定主题资源保证风格统一。
- 方案二中,若MenuItems动态加载,需在加载完成后同步执行模板切换逻辑。
内容的提问来源于stack exchange,提问作者Phoenix404
相关产品推荐
相关产品推荐

