如何设置DataGridColumn的宽度以适应内容("Auto"),但是完全填充MVVM中DataGrid的可用空间?

Sör*_*ren 23 c# wpf xaml datagrid mvvm

我有一个DataGrid包含一些数据的WPF .我想设置列的宽度,使内容适合并永远不会被裁剪(相反,水平滚动条应该变得可见).另外,我希望DataGrid填充整个地方(我正在使用DockPanel).我使用以下代码(简化):

<DataGrid ItemsSource="{Binding Table}">
    <DataGrid.Columns>
        <DataGridTextColumn MinWidth="100" Width="Auto" Header="Column 1" Binding="{Binding Property1}" />
        <DataGridTextColumn MinWidth="200" Width="Auto" Header="Column 2" Binding="{Binding Property2}" />
    </DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)

这显然不是开箱即用的,Width="Auto"因为它总是看起来像这样:

DataGrid:只将行的第一部分标记为

这看起来很丑陋.我想选择整行,或者更好的是填充整个宽度的列,但正如人们所看到的,这不起作用.

如果我Width="*"改用,列的内容会被裁剪掉,这对我来说更糟糕.

我在这里找到了一个类似的问题,并在那里发布了一个解决方法.这可能有效,但我正在使用MVVM模式,因此ItemsSource在ViewModel中得到更新,我无法想到从那里做到这一点的方法,因为我无法访问该ActualWidth属性DataGridColumn.另外,如果可能的话,我只想在XAML中这样做.

我将不胜感激任何帮助.谢谢!

编辑:由于我仍然不知道如何处理它,我开始小小的赏金.关于我可以对我的问题采取什么建议,我会非常高兴.再次感谢!

编辑2:在香肠'回答后,我再次考虑了这些选项.问题是我需要在应用程序运行期间更新WidthMinWidth属性,因此不仅在加载窗口后.我已经尝试过这样的事情了

column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
column.MinWidth = column.ActualWidth;
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
Run Code Online (Sandbox Code Playgroud)

在当底层被解雇的一些事件ItemsSource中的DataGrid被更新.然而,这是不行的,因为ActualWidth财产似乎并没有设置后改变WidthAuto.有没有选择以某种方式"重新"它以便ActualWidth更新属性?谢谢!

sau*_*aus 32

我建议使用您链接的解决方法.它确实有效.在视图的代码隐藏中,在InitializeComponent()之后将以下内容添加到构造函数中:

Griddy.Loaded += SetMinWidths; // I named my datagrid Griddy
Run Code Online (Sandbox Code Playgroud)

并将SetMinWidths定义为:

public void SetMinWidths(object source, EventArgs e )
        {
            foreach (var column in Griddy.Columns)
            {
                column.MinWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
            }
        }
Run Code Online (Sandbox Code Playgroud)

我假设您不想使用此解决方案的原因是您认为MVVM禁止代码隐藏中的代码.但由于这完全是视图特定的逻辑,我认为在这种情况下它是合理的.整个"MVVM禁止代码隐藏中的代码"的事情有点误解.

但是,如果您受样式指南的约束,或者您希望此逻辑可用于应用程序中的所有数据网格,则可以创建一个执行此作业的附加行为:

public class SetMinWidthToAutoAttachedBehaviour 
    {
        public static bool GetSetMinWidthToAuto(DependencyObject obj)
        {
            return (bool)obj.GetValue(SetMinWidthToAutoProperty);
        }

        public static void SetSetMinWidthToAuto(DependencyObject obj, bool value)
        {
            obj.SetValue(SetMinWidthToAutoProperty, value);
        }

        // Using a DependencyProperty as the backing store for SetMinWidthToAuto.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SetMinWidthToAutoProperty =
            DependencyProperty.RegisterAttached("SetMinWidthToAuto", typeof(bool), typeof(SetMinWidthToAutoAttachedBehaviour), new UIPropertyMetadata(false, WireUpLoadedEvent));

        public static void WireUpLoadedEvent(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var grid = (DataGrid)d;

            var doIt = (bool)e.NewValue;

            if (doIt)
            {
                grid.Loaded += SetMinWidths;
            }
        }

        public static void SetMinWidths(object source, EventArgs e)
        {
            var grid = (DataGrid)source;

            foreach (var column in grid.Columns)
            {
                column.MinWidth = column.ActualWidth;
                column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后对于要将此行为应用于的任何数据网格,添加以下内容:

<DataGrid ItemsSource="{Binding Table}" local:SetMinWidthToAutoAttachedBehaviour.SetMinWidthToAuto="true">
Run Code Online (Sandbox Code Playgroud)

然后你的良心以及你的代码隐藏将会很清楚.

  • 嗨,非常感谢!实际上,我不认为完全查看特定的东西不应该在代码隐藏中.问题是ViewGodel中`DataGrid`的内容发生了变化,因此View不知道何时需要再次调用`SetMinWidths`.一旦我的`NotifyPropertyChanged`方法被调用,可能会有一种方式使DataGrid发生变化?我认为这与附加行为有同样的问题,但我可能会找到解决这个问题的方法.很快就会有更多的信息回来.再次感谢! (3认同)

Raf*_*eda 4

使用在模板列内进行文本换行的 TextBlock:

<DataGrid ItemsSource="{Binding Table}">      
    <DataGrid.Columns>          
        <DataGridTextColumn MinWidth="100" Width="Auto" Header="Column 1"
                            Binding="{Binding Property1}" />          
        <DataGridTemplateColumn Width="*" Header="Column 2">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Property2}" TextWrapping="Wrap" />  
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>  
</DataGrid>
Run Code Online (Sandbox Code Playgroud)

  • 我不想在特定列中有一个滚动条,而是在整个数据网格中有一个滚动条,如果我将列的宽度设置为“自动”并且空间不够,它也会出现......它看起来很如果每个单元格中都有滚动条,那就不好了...... (3认同)