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

WinUI 3求助:NavigationView折叠时ListViewItem宽度不匹配ListView

解决方案:NavigationView折叠时嵌入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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 19:44:56