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

WPF DataGrid列自适应内容且末列填余空,支持横向滚动的实现方案

WPF DataGrid 列宽自适应与滚动条需求解决方案

问题场景与需求

  • 使用WPF的DataGrid展示ViewModel列表,数据通过按钮绑定FolderBrowserDialog从文件夹加载;启动时若存在历史路径,会自动填充DataGrid,因此存在已填充和未填充两种状态
  • 核心需求:
    • 数据填充后,所有列自动适配内容宽度,末列填充剩余空白以支持整行选中
    • 窗口缩小至DataGrid宽度小于列总宽度时,显示横向滚动条,且列宽保持内容宽度
    • 上述效果需在按钮触发填充和启动自动填充两种场景下均生效

已尝试的两种方案

方案1:设置列Width为Auto,末列设为*

  • 优点:整行可选中
  • 缺点:窗口调整时列被挤压且无横向滚动条;空DataGrid填充数据后列未自适应内容
  • 代码:
<Grid Grid.Column="0"
      Grid.ColumnSpan="2"
      Grid.Row="3" 
      Background="#f7f5f2"
      Margin="10">
    <DataGrid x:Name="ModList" 
              ItemsSource="{Binding Mods}"
              Style="{DynamicResource DataGridStyle1}" 
              CellStyle="{DynamicResource DataGridCellStyle1}" 
              ColumnHeaderStyle="{DynamicResource DataGridColumnHeaderStyle1}" 
              RowStyle="{DynamicResource DataGridRowStyle1}"
              RowDetailsTemplate="{DynamicResource DataGridRowDetailsTemplate1}"
              Margin="10"
              dd:DragDrop.IsDragSource="True" 
              dd:DragDrop.IsDropTarget="True" 
              dd:DragDrop.SelectDroppedItems="True" 
              dd:DragDrop.DropHandler="{Binding}" 
              dd:DragDrop.DropTargetAdornerBrush="#484D54">
     
        <DataGrid.Columns>
            <DataGridTemplateColumn x:Name="DataGridColumnEnabled"
                                    Width="Auto">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <CheckBox x:Name="CheckBoxIsEnabled"
                                  IsChecked="{Binding IsEnabled, UpdateSourceTrigger=PropertyChanged}"
                                  Command="{Binding DataContext.ToggleCheckBoxCommand, RelativeSource={RelativeSource AncestorType=Window}}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn x:Name="DataGridColumnLoadorder"
                                Header="Loadorder" 
                                IsReadOnly="True" 
                                Width="Auto" 
                                Binding="{Binding LoadOrder, UpdateSourceTrigger=PropertyChanged}" 
                                CanUserSort="False"/>
            <DataGridTextColumn x:Name="DataGridColumnMod"
                                Header="Mod" 
                                IsReadOnly="True"
                                Width="Auto"
                                Binding="{Binding DisplayName}" 
                                CanUserSort="False"
                                VirtualizingPanel.VirtualizationMode="Standard"/>
            <DataGridTemplateColumn x:Name="DataGridColumnNotification"
                                    IsReadOnly="True"
                                    Width="Auto"
                                    CanUserSort="False">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="/WarningIcon.png"
                               Height="16"
                               Width="16"
                               HorizontalAlignment="Stretch"
                               VerticalAlignment="Stretch"
                               Cursor="Help"
                               Visibility="{Binding HasConflicts}">
                            <ToolTipService.ToolTip>
                                <ToolTip Content="Mod(s) detected altering the same asset(s). &#x0a;This may be intentional, please check before committing loadorder."/>
                            </ToolTipService.ToolTip>
                        </Image>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn x:Name="DataGridColumnAuthor"
                                Header="Author" 
                                IsReadOnly="True" 
                                Width="Auto" 
                                Binding="{Binding Author}" 
                                CanUserSort="False"/>
            <DataGridTextColumn x:Name="DataGridColumnVersion"
                                Header="Version" 
                                IsReadOnly="True" 
                                Width="Auto"
                                Binding="{Binding Version}" 
                                CanUserSort="False"/>
            <DataGridTextColumn x:Name="DataGridColumnSource"
                                Header="Source"
                                IsReadOnly="True"
                                Width="*"
                                Binding="{Binding Source}"
                                CanUserSort="False"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

方案2:方案1基础上后台设置列MinWidth

  • 优点:窗口调整时显示横向滚动条
  • 缺点:空DataGrid填充数据后列仍未自适应内容
  • 代码:
    • XAML新增事件:SizeChanged="ModList_SizeChanged"
    • 后台代码:
public partial class MainWindow : Window
{
    
    // Other code

    private void ModList_SizeChanged(object sender, EventArgs e)
    {
        DataGridColumnEnabled.MinWidth = DataGridColumnEnabled.ActualWidth;
        DataGridColumnLoadorder.MinWidth = DataGridColumnLoadorder.ActualWidth;
        DataGridColumnMod.MinWidth = DataGridColumnMod.ActualWidth;
        DataGridColumnNotification.MinWidth = DataGridColumnNotification.ActualWidth;
        DataGridColumnAuthor.MinWidth = DataGridColumnAuthor.ActualWidth;
        DataGridColumnVersion.MinWidth = DataGridColumnVersion.ActualWidth;
        DataGridColumnSource.MinWidth = 200;
    }
}

可行实现方案

针对方案2的缺点,需要在数据填充完成后主动触发列宽自适应,同时保留MinWidth的设置逻辑,具体步骤如下:

1. 监听数据集合变化

在窗口构造函数中监听ViewModel的Mods集合变化,确保数据加载完成后触发自适应:

public MainWindow()
{
    InitializeComponent();
    var viewModel = DataContext as YourViewModelType;
    viewModel.Mods.CollectionChanged += Mods_CollectionChanged;
}

private void Mods_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
    // 仅在添加数据或重置集合后执行自适应
    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add || 
        e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Reset)
    {
        // 延迟执行,确保数据渲染完成
        Dispatcher.BeginInvoke(new Action(() =>
        {
            AutoFitColumns();
            UpdateColumnMinWidths();
        }), System.Windows.Threading.DispatcherPriority.Render);
    }
}

2. 实现列宽自适应与MinWidth更新方法

private void AutoFitColumns()
{
    // 遍历非末列,设置为Auto适配内容
    foreach (var column in ModList.Columns)
    {
        if (column != DataGridColumnSource)
        {
            column.Width = DataGridLength.Auto;
        }
    }
    // 末列设置为*填充剩余空间
    DataGridColumnSource.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
}

private void UpdateColumnMinWidths()
{
    // 更新所有列的MinWidth为当前实际宽度,防止窗口缩小时被挤压
    DataGridColumnEnabled.MinWidth = DataGridColumnEnabled.ActualWidth;
    DataGridColumnLoadorder.MinWidth = DataGridColumnLoadorder.ActualWidth;
    DataGridColumnMod.MinWidth = DataGridColumnMod.ActualWidth;
    DataGridColumnNotification.MinWidth = DataGridColumnNotification.ActualWidth;
    DataGridColumnAuthor.MinWidth = DataGridColumnAuthor.ActualWidth;
    DataGridColumnVersion.MinWidth = DataGridColumnVersion.ActualWidth;
    DataGridColumnSource.MinWidth = Math.Max(200, DataGridColumnSource.ActualWidth);
}

3. 调整SizeChanged事件逻辑

修改原事件方法,避免重复设置MinWidth,仅处理滚动条显示逻辑:

private void ModList_SizeChanged(object sender, EventArgs e)
{
    var totalMinWidth = ModList.Columns.Sum(c => c.MinWidth);
    if (ModList.ActualWidth < totalMinWidth)
    {
        ModList.HorizontalScrollBarVisibility = ScrollBarVisibility.Visible;
    }
    else
    {
        DataGridColumnSource.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
        ModList.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
    }
}

额外优化

  • 启动自动填充场景:在Window_Loaded事件中调用AutoFitColumns()和UpdateColumnMinWidths(),确保窗口加载完成后列宽适配
  • 对于DataGridTemplateColumn,确保模板内控件的HorizontalAlignment设为Stretch,避免限制列宽自适应

内容的提问来源于stack exchange,提问作者Merlock

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 12:17:10