如何设置 DataGridColumn 的宽度以适应内容(“自动"),但完全填充 MVVM 中 DataGrid 的可用空间? [英] How can I set the width of a DataGridColumn to fit contents ("Auto"), but completely fill the available space for the DataGrid in MVVM?

查看:23
本文介绍了如何设置 DataGridColumn 的宽度以适应内容(“自动"),但完全填充 MVVM 中 DataGrid 的可用空间?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a WPF DataGrid that contains some data. I would like to set the width of the columns such that the content fits in and never gets cropped (instead, a horizontal scroll bar should become visible). Additionally, I want the DataGrid to fill the whole place available (I am working with a DockPanel). I am using the following code (simplified):

<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>

这显然不适用于 Width="Auto",因为它总是看起来像这样:

This apparently does not work out of the box with Width="Auto" as it always looks something like this:

这显然很难看.我想选择整行,或者,哪个会更好,填充整个宽度的列,但正如人们所见,这行不通.

This obviously looks ugly. I would like to have the whole row selected, or, which would be much better, the columns to fill the whole width, but as one can see, this does not work.

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

If I use Width="*" instead, the content of the columns gets cropped which is even worse for me.

我在这里发现了一个类似的问题,并在那里发布了解决方法.这可能有效,但我正在使用 MVVM 模式,因此 ItemsSource 在 ViewModel 中得到更新,我无法考虑从那里执行此操作的方法,因为我无法访问 ActualWidthDataGridColumn 属性.另外,如果可能,我只想在 XAML 中执行此操作.

I found a similar question here, and a workaround was posted there. This may work, but I am working with the MVVM pattern, so the ItemsSource gets updated in the ViewModel and I cannot think about a way of doing it from there, because I cannot access the ActualWidth property of the DataGridColumn. Also, I would like to do it only in XAML if possible.

我将不胜感激.谢谢!

由于我仍然不知道该怎么做,所以我开始了一个小赏金.我会很高兴有人可以对我的问题做些什么的建议.再次感谢!

As I still don't have a clue what to do about it, I start a small bounty. I would be very happy about a suggestion what one could do about my problem. Thanks again!

编辑 2:在 saus 的回答之后,我再次考虑了选项.问题是我还需要在应用程序运行期间更新 WidthMinWidth 属性,所以不仅仅是在加载窗口之后.我已经尝试做类似的事情

Edit 2: After saus' answer I thought about the options again. The problem is that I need to update the Width and the MinWidth properties also during the application is running, so not only after loading the window. I already tried to do something like

column.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);
column.MinWidth = column.ActualWidth;
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);

在更新 DataGrid 的基础 ItemsSource 时触发的某些事件.但是,这不起作用,因为在 Auto 上设置 Width 后,ActualWidth 属性似乎没有改变.是否可以选择以某种方式重新绘制"它以更新 ActualWidth 属性?谢谢!

in some event that is fired when the underlying ItemsSource of the DataGrid is updating. However, this does not work, as the ActualWidth property does not seem to change after setting the Width on Auto. Is there an option to somehow "repaint" it in order to get the ActualWidth property updated? Thanks!

推荐答案

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

I would suggest using the workaround that you linked to. It does work. In the codebehind of your view, add the following to the constructor after InitializeComponent():

Griddy.Loaded += SetMinWidths; // I named my datagrid Griddy

并将 SetMinWidths 定义为:

and define SetMinWidths as:

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

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

I'm assuming that the reason you don't want to use this solution is that you believe that MVVM prohibits code in the codebehind. But since this is entirely view specific logic I believe that it is justified in this case. The whole "MVVM prohibits code in the codebehind" thing is a bit of a misconception.

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

But if you are bound by style guides, or you want this logic to be available for all datagrids in your app, you can make an attached behaviour that does the job like this:

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);
            }
        }
    }

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

and then for any datagrid that you want to apply this behaviour to, add the following:

<DataGrid ItemsSource="{Binding Table}" local:SetMinWidthToAutoAttachedBehaviour.SetMinWidthToAuto="true">

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

And then your conscience, as well as your codebehind, will be clear.

这篇关于如何设置 DataGridColumn 的宽度以适应内容(“自动"),但完全填充 MVVM 中 DataGrid 的可用空间?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆