WinUI 3:切换选中项时如何折叠导航菜单项
WinUI 3 导航菜单切换时折叠未选中项且保留选中动画的解决方法
你遇到的问题是因为在SelectionChanged事件里同步修改非选中项的IsExpanded属性,打断了导航菜单控件内部的选中指示器动画流程——控件还在处理选中状态的过渡动画,就被强制修改了展开状态,导致动画异常。
下面是两种可行的解决思路:
方法一:延迟执行折叠操作
通过延迟修改IsExpanded,让控件先完成选中动画,再处理折叠逻辑:
步骤1:提前收集所有导航菜单项
先在导航菜单加载时,递归收集所有层级的菜单项,避免每次切换都重新遍历:
private List<NavigationViewItemBase> _allNavItems = new(); private void NavView_Loaded(object sender, RoutedEventArgs e) { var navView = sender as NavigationView; CollectAllItems(navView.MenuItems, _allNavItems); } private void CollectAllItems(IEnumerable menuItems, List<NavigationViewItemBase> itemsList) { foreach (var item in menuItems) { if (item is NavigationViewItemBase navItem) { itemsList.Add(navItem); if (navItem is NavigationViewItem parentItem) { CollectAllItems(parentItem.MenuItems, itemsList); } } } }
步骤2:在SelectionChanged中延迟折叠
用Task.Delay让折叠操作等动画完成后再执行:
private async void NavView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { // 等待100ms让选中动画完成,可根据实际效果微调时长 await Task.Delay(100); foreach (var item in _allNavItems) { if (item is NavigationViewItem navItem && navItem != args.SelectedItem) { navItem.IsExpanded = false; } } }
方法二:MVVM模式下的绑定控制
如果用MVVM开发,可以给每个菜单项的ViewModel添加IsSelected和IsExpanded属性,通过绑定实现联动:
- ViewModel中,当某个项的
IsSelected设为true时,遍历其他项并延迟设置IsExpanded = false - XAML中绑定
NavigationViewItem的IsSelected和IsExpanded到ViewModel对应属性:
<NavigationViewItem IsSelected="{Binding IsSelected}" IsExpanded="{Binding IsExpanded}" />
这种方式更贴合MVVM架构,也能避免直接操作控件带来的状态冲突。
注意点
- 延迟时间不用太长,100ms基本能覆盖WinUI 3的选中动画时长,可根据实际显示效果调整
- 如果菜单有动态加载的项,要在项更新后重新调用收集方法,确保所有项都被纳入处理
内容的提问来源于stack exchange,提问作者Daan
相关产品推荐
相关产品推荐

