首页 文章

如何使WPF数据网格中的最后一列占用所有左侧空间,总是?

提问于
浏览
26

标准WPF 4 Datagrid .

假设我的数据网格宽200像素,2列 . 我希望列总是占用整个空间,这意味着如果用户将第一列调整为50像素,则最后一列将为150 .

最初我为第1列设置宽度为100像素,为最后一列设置宽度(在XAML中) .

我认为问题在于移除虚拟的第3列,如下所述:

http://wpf.codeplex.com/Thread/View.aspx?ThreadId=58939

但实际上没有区别 - 仍然,当调整列的大小时,我在右边获得了一些额外的空间 - 使用虚拟列,它是一个虚拟列(默认为白色),没有它,它是空的空间(灰色的默认) .

QUESTION :如何强制执行约束,无论用户如何调整列的大小,

sum(columns width)==datagrid width

编辑

是的,我使用WPF 4 .

WORKAROUND

我将其中一个答案标记为解决方案,但实际上它并不是WPF设计的解决方案 . 它只是WPF最多可以做的事情,它并不是很好 - 首先,列的选项CanUserResize实际上是IsResizeable,当打开时这个选项与Width设置为*相矛盾 . 因此,如果没有一些非常聪明的技巧,你最终会:

  • datagrid,其最后一列在表面上可调整大小但事实上它不是,并且右边的小空间被显示(即虚拟列不可调整大小) - 对于最后一列:CanUserResize = true,Width = *

  • datagrid哪个最后一列不能被用户调整大小并且相应地显示,最初没有显示右边的空格,但是当用户调整datagrid的任何元素时可以显示 - 对于最后一列:CanUserResize = false,Width = *

到目前为止,我可以看到WPF datagrid的两个问题:

  • 误导性命名

  • 功能矛盾

我仍然倾听如何真正解决这个问题 .

4 回答

  • 5

    我刚刚将其实现为附加行为 . 问题是当你将DataGrid的最后一列设置为*时,它会调整大小以适应,但随后其他单元格的所有自动装配都会混乱 . 要解决此问题,附加行为会对其他(非最后一个)单元格进行手动自动调整 .

    这在调整其他列的大小时也有效 - 一旦加载,您可以调整大小,最后一列将始终填充 . 请注意,此行为在Loaded事件上有效

    // Behavior usage: <DataGrid DataGridExtensions.LastColumnFill="True"/>
    public class DataGridExtensions
    {
        public static readonly DependencyProperty LastColumnFillProperty = DependencyProperty.RegisterAttached("LastColumnFill", typeof(bool), typeof(DataGridExtensions), new PropertyMetadata(default(bool), OnLastColumnFillChanged));
    
        public static void SetLastColumnFill(DataGrid element, bool value)
        {
            element.SetValue(LastColumnFillProperty, value);
        }
    
        public static bool GetLastColumnFill(DataGrid element)
        {
            return (bool)element.GetValue(LastColumnFillProperty);
        }
    
        private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var dataGrid = d as DataGrid;
            if (dataGrid == null) return;
    
            dataGrid.Loaded -= OnDataGridLoaded;
            dataGrid.Loaded += OnDataGridLoaded;
        }        
    
        private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null) return;
    
            var lastColumn = dataGrid.Columns.LastOrDefault();
            if(lastColumn != null)
                lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
    
            // Autofit all other columns
            foreach (var column in dataGrid.Columns)
            {
                if (column == lastColumn) break;
    
                double beforeWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
                double sizeCellsWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
                double sizeHeaderWidth = column.ActualWidth;
                column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
            }
        }
    }
    
  • 0

    将数据网格的宽度设置为“自动” . 您允许列在网格本身内正确调整大小,但您已将宽度硬连接到200 .

    UPDATE :根据@micas 's comment, I may have misread. If that'的情况,尝试使用100表示左列的宽度,使用100 *表示右列(注意星号) . 这会将右列的宽度默认为100,但允许它调整大小以填充网格 .

  • 21

    您可以在代码上设置列宽为星号 . 在构造函数中,添加:

    Loaded += (s, e) => dataGrid1.Columns[3].Width =
    new DataGridLength(1, DataGridLengthUnitType.Star);
    
  • 4

    预先警告:这是一个黑客......

    我在Dr. ABT方法中注册了"AutoGeneratedColumns"事件Dr. ABT 's class and copied the Loaded method into it, and it works. I haven'尚未经过彻底的测试,所以YMMV .

    我的改变:

    private static void OnLastColumnFillChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var dataGrid = d as DataGrid;
            if (dataGrid == null) return;
    
            dataGrid.Loaded -= OnDataGridLoaded;
            dataGrid.Loaded += OnDataGridLoaded;
    
            dataGrid.AutoGeneratedColumns -= OnDataGrid_AutoGeneratedColumns;
            dataGrid.AutoGeneratedColumns += OnDataGrid_AutoGeneratedColumns;
        }
    
        private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null) return;
    
            var lastColumn = dataGrid.Columns.LastOrDefault();
            if (lastColumn != null)
                lastColumn.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
    
            // Autofit all other columns
            foreach (var column in dataGrid.Columns)
            {
                if (column == lastColumn) break;
    
                double beforeWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToCells);
                double sizeCellsWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.SizeToHeader);
                double sizeHeaderWidth = column.ActualWidth;
                column.MinWidth = Math.Max(beforeWidth, Math.Max(sizeCellsWidth, sizeHeaderWidth));
            }
        }
    

    哦,不要忘记将命名空间添加到XAML声明中! :)

    顶部:

    xmlns:ext="clr-namespace:TestProject.Extensions"
    

    然后在DataGrid声明中:

    ext:DataGridExtensions.LastColumnFill="True"
    

    Update :我说里程会有所不同!我当然做到了 .

    整个“自动调整列”位导致我的一些DataGrid中的列具有可变数量的列,只能与列 Headers 一样宽 . 我删除了那部分,现在它似乎正在处理应用程序中的所有DataGrids .

    我现在有:

    private static void OnDataGrid_AutoGeneratedColumns(object sender, EventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null) return;
    
            UpdateColumnWidths(dataGrid);
    
        }
    
        private static void OnDataGridLoaded(object sender, RoutedEventArgs e)
        {
            var dataGrid = sender as DataGrid;
            if (dataGrid == null) return;
    
            UpdateColumnWidths(dataGrid);
        }
    
        private static void UpdateColumnWidths(DataGrid dataGrid)
        {
            var lastColumn = dataGrid.Columns.LastOrDefault();
            if (lastColumn == null) return;
    
            lastColumn.Width = new DataGridLength(1.0d, DataGridLengthUnitType.Star);
    
        }
    

相关问题