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

如何实现WPF DataGrid拖动右侧边缘均匀缩小列宽(仿Visual Studio)

WPF DataGrid拖动右边缘均匀调整所有列宽度实现方案

需要实现类似Visual Studio的功能:拖动WPF DataGrid的右侧边缘时,让所有列的宽度按比例均匀缩小或放大。目前调整DataGrid属性后未达到预期效果,现有DataGrid代码如下:

<DataGrid 
      x:Name="MainDataGridDop"  
      IsEnabled="{Binding AppUnlocked}"
      SelectionMode="Single"
      GridLinesVisibility="All"
      HorizontalGridLinesBrush="LightGray"
      VerticalGridLinesBrush="LightGray"
      AlternationCount="2"
      AutoGenerateColumns="False"
      FrozenColumnCount ="2" 
      CanUserAddRows="False" 
      CanUserSortColumns="False"
      ItemsSource="{Binding AddVolumesServiceList}"
      SelectedValue="{Binding SelectedAddVolumesRow, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
      MouseRightButtonDown="MainDataGridDop_MouseRightButtonDown"
      ScrollViewer.CanContentScroll="False" 
      ScrollViewer.VerticalScrollBarVisibility="Auto"
      ScrollViewer.HorizontalScrollBarVisibility="Auto"
      CanUserReorderColumns="False" 
      HorizontalContentAlignment="Stretch"                                          
      VerticalContentAlignment="Stretch" 
      UseLayoutRounding="False"
      BorderBrush="#FFDDDDDD" 
      Background="#FFF9F9F9"
      CanUserResizeColumns="True"
      MinWidth="150" Width="Auto" MinHeight="15" ColumnWidth="*" Margin="0,0,0,1"
>
<!-- 列定义 -->
</DataGrid>

实现思路与代码

默认情况下,ColumnWidth="*"仅在初始化时按比例分配列宽,拖动DataGrid右边缘不会同步调整列宽。要实现目标功能,需监听控件尺寸变化,结合列宽比例动态更新每列宽度。

步骤1:修改XAML添加事件

给DataGrid添加Loaded和SizeChanged事件,用于初始化比例和响应尺寸变化:

<DataGrid 
      x:Name="MainDataGridDop"  
      <!-- 原有属性保留 -->
      Loaded="MainDataGridDop_Loaded"
      SizeChanged="MainDataGridDop_SizeChanged"
>
<!-- 列定义 -->
</DataGrid>

步骤2:后台逻辑实现

在C#代码中编写事件处理逻辑,记录列宽比例并动态调整:

private List<double> _columnWidthRatios = new List<double>();
private double _totalInitialNonFrozenWidth;

private void MainDataGridDop_Loaded(object sender, RoutedEventArgs e)
{
    var dataGrid = sender as DataGrid;
    if (dataGrid == null) return;

    // 提取非冻结列,计算初始总宽度和各列比例
    var nonFrozenColumns = dataGrid.Columns.Skip(dataGrid.FrozenColumnCount);
    _totalInitialNonFrozenWidth = nonFrozenColumns.Sum(col => col.ActualWidth);

    foreach (var column in nonFrozenColumns)
    {
        _columnWidthRatios.Add(column.ActualWidth / _totalInitialNonFrozenWidth);
    }
}

private void MainDataGridDop_SizeChanged(object sender, SizeChangedEventArgs e)
{
    var dataGrid = sender as DataGrid;
    if (dataGrid == null || _columnWidthRatios.Count == 0) return;

    // 计算非冻结列可分配的新总宽度(扣除冻结列、内边距、网格线宽度)
    var frozenTotalWidth = dataGrid.Columns.Take(dataGrid.FrozenColumnCount).Sum(col => col.ActualWidth);
    var gridLinesOffset = dataGrid.GridLinesVisibility == GridLinesVisibility.All ? dataGrid.Columns.Count * 1 : 0;
    var newNonFrozenTotalWidth = dataGrid.ActualWidth 
                                 - frozenTotalWidth 
                                 - dataGrid.Padding.Left 
                                 - dataGrid.Padding.Right 
                                 - gridLinesOffset;

    // 按比例更新每列宽度
    var nonFrozenColumns = dataGrid.Columns.Skip(dataGrid.FrozenColumnCount).ToList();
    for (int i = 0; i < nonFrozenColumns.Count; i++)
    {
        nonFrozenColumns[i].Width = new DataGridLength(_columnWidthRatios[i] * newNonFrozenTotalWidth, DataGridLengthUnitType.Pixel);
    }
}

注意事项

  • 冻结列宽度保持固定,不参与缩放,和Visual Studio的行为一致。
  • 网格线宽度的偏移值可根据实际显示效果调整。
  • 若允许用户手动调整列宽,可添加ColumnWidthChanged事件,在用户调整后重新计算并更新_columnWidthRatios,确保后续缩放基于最新比例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:55:10