Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何设置DataGridColumn的宽度以适应内容(“Auto”),同时完全填充MVVM中DataGrid的可用空间?_C#_Wpf_Xaml_Mvvm_Datagrid - Fatal编程技术网

C# 如何设置DataGridColumn的宽度以适应内容(“Auto”),同时完全填充MVVM中DataGrid的可用空间?

C# 如何设置DataGridColumn的宽度以适应内容(“Auto”),同时完全填充MVVM中DataGrid的可用空间?,c#,wpf,xaml,mvvm,datagrid,C#,Wpf,Xaml,Mvvm,Datagrid,我有一个包含一些数据的WPFDataGrid。我想设置列的宽度,以使内容适合并且永远不会被裁剪(相反,水平滚动条应该是可见的)。此外,我希望DataGrid能够填满整个可用空间(我正在使用DockPanel)。我正在使用以下代码(简化): 在某些事件中,当DataGrid的基础ItemsSource正在更新时触发。但是,这不起作用,因为在Auto上设置Width后,ActualWidth属性似乎没有改变。是否有一个选项以某种方式“重新绘制”它,以便更新ActualWidth属性?谢谢 在模板列中

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


在某些事件中,当
DataGrid
的基础
ItemsSource
正在更新时触发。但是,这不起作用,因为在
Auto
上设置
Width
后,
ActualWidth
属性似乎没有改变。是否有一个选项以某种方式“重新绘制”它,以便更新
ActualWidth
属性?谢谢

在模板列中使用文本换行的文本块:

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

这个怎么样:

对于列的MinWidth,您可以设置一个绑定到dataGrid的ScrollContent的宽度,并使用一个转换器将此宽度除以列数

您需要为转换器编写一些代码,但这将保持MVVM结构的完整性

可能是一个长期的尝试,但没有时间尝试它

编辑:我对此做了更多的思考,然后出现了一个pb:如果你有一个大专栏和几个小专栏,它将无法正常工作。我假设所有的col都是相同的宽度,这显然不是这里的情况


不过,您可能希望以这种方式进行探索。通过转换器在宽度上使用绑定是我能想到的唯一可行的方法:因为在计算列的宽度时,基本上有两个条件需要考虑,所以没有简单的方法可以做到这一点。

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

并将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);
            }
        }
我假设您不想使用此解决方案的原因是您认为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);
            }
        }
    }
然后,对于要应用此行为的任何datagrid,添加以下内容:

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


然后,你的良心和你的代码隐藏就会清楚了。

强制最后一列占用datagrid中所有剩余的空间

grid.Columns[grid.Columns.Count -1].Width = new 
                  DataGridLength(250, DataGridLengthUnitType.Star);

我将
事件
添加到
数据网格
,根据
数据网格
的实际宽度重新定义其宽度:

 private static void OnLoaded(object sender, RoutedEventArgs e)
    {
        DataGrid dg = sender as DataGrid;
        foreach (var column in dg.Columns)
        {
            column.Width = new DataGridLength(dg.ActualWidth / dg.Columns.Count, DataGridLengthUnitType.Pixel);
        }
    }
该行:

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

他完全没有理智。
datagridlengthunitype.Star的定义将列的宽度缩小到其最小宽度,并使其宽度为静态且不可编辑。

将其用于任何要适合其内容的列:
Width=“SizeToCells”

谢谢你的建议,但我不想包装文本。如上所述,我希望在文本变得太宽时立即获得一个垂直滚动条。模板列的要点是,您可以在DataTemplate中使用任何适合您需要的控件,例如,我不希望在特定列中有滚动条,但是,如果我将列的宽度设置为“Auto”,并且空间不够,那么整个datagrid也会出现一个。。。如果你在每个单元格中都有滚动条,那就太糟糕了……我不知道你想在这里做什么。如果列的宽度比
DataGrid
宽,您需要一个垂直滚动条,而不希望文本换行?你是说水平滚动条吗?否则,这对我来说毫无意义,但也许我只是在这里慢了一点:)谢谢你的提示!当然,我指的是水平滚动条,否则就没有任何意义;-)好的,谢谢你的主意,我会考虑的。然而,我确实有一个专栏比其他专栏宽得多,所以它不适用于第一个建议。我认为您是对的,我需要为列的宽度使用绑定(我也是这么认为的),但是为每个列找到合适的minwidth/width仍然是一个挑战^^^^它肯定会的。^^如果我可以添加一条建议:如果可以避免,请不要将MinWidth属性与Width属性结合使用。它会导致剧烈的头痛。e、 g:将minWidth设置为100,然后将width设置为80,控件的宽度将为80:如果通过程序设置,宽度将接管minWidth…嗨,非常感谢!实际上,我不认为完全视图特定的东西不应该出现在代码背后。问题在于,
DataGrid
的内容在ViewModel中发生了变化,因此视图不知道何时必须再次调用
SetMinWidths
。也许有一种方法,只要调用我的
NotifyPropertyChanged
方法,DataGrid就会改变?我认为这与附加的行为是相同的问题,但我可能会找到一种方法来解决这个问题。很快就会回来提供更多信息。再次感谢!看到我的帖子,我编辑了它:不幸的是,我没有让它像那样工作。出于上述原因。我们是否需要取消订阅该事件以避免内存泄漏?对我来说,此模式将所有列缩小到其最小大小,因此正好相反。此解决方案的另一个缺陷是它完全无法编辑列的宽度。
grid.Columns[grid.Columns.Count -1].Width = new 
                  DataGridLength(250, DataGridLengthUnitType.Star);
 private static void OnLoaded(object sender, RoutedEventArgs e)
    {
        DataGrid dg = sender as DataGrid;
        foreach (var column in dg.Columns)
        {
            column.Width = new DataGridLength(dg.ActualWidth / dg.Columns.Count, DataGridLengthUnitType.Pixel);
        }
    }
column.Width = new DataGridLength(1, DataGridLengthUnitType.Star);