WinUI 3求助:NavigationView折叠时ListViewItem宽度不匹配ListView
核心问题拆解
你遇到的问题本质是:
- 自定义的NavigationViewItem模板未继承原生控件的自适应逻辑
- ListView及其子项未正确响应NavigationView的折叠/展开状态变化
- 直接替换ItemContainerStyle会丢失WinUI/UWP原生的ListViewItem样式(包括选中状态指示器)
分步解决
1. 修复ListViewItem样式,保留原生特性
不要直接新建Style,基于系统默认的ListViewItem样式修改,既保留原有交互效果,又能设置水平对齐:
<ListView.ItemContainerStyle> <Style TargetType="ListViewItem" BasedOn="{StaticResource ListViewItemStyle}"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> <!-- 折叠时内容居中,展开时左对齐 --> <Setter Property="HorizontalAlignment" Value="{Binding IsPaneOpen, ElementName=YourNavigationView, Converter={StaticResource BoolToHorizontalAlignmentConverter}}" /> </Style> </ListView.ItemContainerStyle>
新增Bool转HorizontalAlignment的转换器:
public class BoolToHorizontalAlignmentConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { return (bool)value ? HorizontalAlignment.Left : HorizontalAlignment.Center; } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }
在资源中声明转换器:
<converters:BoolToHorizontalAlignmentConverter x:Key="BoolToHorizontalAlignmentConverter" />
2. 绑定ListView宽度到NavigationView的紧凑模式宽度
确保折叠时ListView的宽度和原生NavigationViewItem一致:
<ListView x:Name="lstvSC" Width="{Binding PaneCompactWidth, ElementName=YourNavigationView}" HorizontalAlignment="Stretch" ...>
3. 动态切换文本显示和图标对齐
绑定NavigationView的IsPaneOpen控制文本可见性,同时调整图标边距:
<DataTemplate x:DataType="models:CM"> <Grid HorizontalAlignment="Stretch" ToolTipService.ToolTip="{x:Bind MenuItemName}"> <BitmapIcon Width="24" Margin="{Binding IsPaneOpen, ElementName=YourNavigationView, Converter={StaticResource BoolToMarginConverter}}" UriSource="{x:Bind IP, Converter={StaticResource SCIconConverter}}" /> <TextBlock VerticalAlignment="Center" Text="{x:Bind MenuItemName}" Visibility="{Binding IsPaneOpen, ElementName=YourNavigationView, Converter={StaticResource BoolToVisibilityConverter}}" /> </Grid> </DataTemplate>
对应的Margin转换器(展开时保留原有边距,折叠时居中):
public class BoolToMarginConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, string language) { return (bool)value ? new Thickness(-4,0,0,0) : new Thickness(0); } public object ConvertBack(object value, Type targetType, object parameter, string language) { throw new NotImplementedException(); } }
4. 修正NavigationViewItem的模板
移除自定义的Template,使用原生模板自动处理宽度:
<NavigationViewItem Visibility="{x:Bind ViewModel.ShowSC, Converter={StaticResource BoolToVisibilityConverter}, Mode=OneWay}"> <Grid x:Name="scOuterGrid" MinHeight="100" HorizontalAlignment="Stretch"> <!-- 你的ListView代码 --> </Grid> </NavigationViewItem>
5. 处理Header的显示逻辑
折叠时隐藏ListView的Header,避免布局错乱:
<ListView.Header> <TextBlock x:Name="lstviewSH" Margin="15,15,0,15" FontSize="14" FontWeight="SemiBold" Foreground="{ThemeResource TextBoxForegroundHeaderThemeBrush}" OpticalMarginAlignment="TrimSideBearings" Text="SC" Visibility="{Binding IsPaneOpen, ElementName=YourNavigationView, Converter={StaticResource BoolToVisibilityConverter}}" /> </ListView.Header>
关键注意事项
- 所有绑定的
ElementName=YourNavigationView替换为你实际的NavigationView控件名称 - 转换器需放在正确的命名空间下,并在资源中声明
- 测试时确认拖放和重排序功能正常,避免样式修改影响交互
内容的提问来源于stack exchange,提问作者JoeTomks
相关产品推荐
相关产品推荐

