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