如何调整WPF DataGrid的大小以适应其内容?

目的

我想为DataGrid设置这样的大小(标准,来自WPF),因此所有单元格(文本)都是完全可见的。 我有一个带有DockPanel的窗口,里面有DataGrid,所以当我调整窗口大小时,所有嵌套的小部件(DockPanel和DataGrid)都会相应地resize。

示例(编辑-1)

假设您有100像素宽的窗口,并且您有一列DataGrid,该单元格是“快速棕色狐狸……”(400像素宽)。 因此,DataGrid应该调整为400像素(可能更多,因为填充),窗口也应该调整为400像素(由于填充也更多)。

我没有找到任何标准方法来做到这一点(AFAIK WPF提供了将内容剪辑到所需宽度的方法,我的问题正好相反),所以我提出了这样丑陋的解决方法,这不太合适。

解决方法

  1. 迭代DataGrid标头(假设它们只是字符串)并计算文本所需的宽度
  2. 迭代每列的DataGrid行(假设它们是TextBlock或TextBox)并计算文本所需的最大宽度 – 为TextBlock / TextBox添加水平填充,为DataGrid单元添加水平边距
  3. 对列的DataGrid ActualWidth和(2)中计算的最大宽度之间的所有差异求和
  4. 通过(3)中计算的差值增加窗口宽度

问题

我做了几次测试,在某些情况下计算出的宽度太大(这是一个小问题),因为有些情况太小了。 问题从它的核心过程开始 – 计算TextBox / TextBlock所需的宽度,计算出的宽度总是比它应该小1个单位(如果我将宽度设置为计算宽度,则始终剪切文本中的1个像素)。

那么我忽略了哪个因素呢? 或者更好 – 是否已经有一些方法可以调整DataGrid以适应其内容?

代码

计算文本所需的宽度(此处为TextBlock):

public static double TextWidth(this TextBlock widget, string text) { var formattedText = new FormattedText(text, // can use arbitrary text System.Globalization.CultureInfo.CurrentCulture, widget.FlowDirection, widget.FontFamily.GetTypefaces().FirstOrDefault(), widget.FontSize, widget.Foreground); return formattedText.Width+widget.Padding.Left+widget.Padding.Right; } 

调整窗口大小以适应DataGrid内容(ugly_factor是丑陋的解决方法;-)因为我没有弄清楚如何正确修复它我将它设置为1.3,这样我的窗口“永远不会”太小):

  public static void AdjustWidthToDataGrid(this Window window, DataGrid dataGrid, double ugly_factor) { var max_widths = dataGrid.Columns.Select(it => window.TextWidth(it.Header as string) * ugly_factor).ToArray(); foreach (var row in Enumerable.Range(0, dataGrid.Items.Count)) foreach (var col in Enumerable.Range(0, dataGrid.Columns.Count)) { var cell = dataGrid.GetCell(row, col); double width = 0; if (cell.Content is TextBlock) width = (cell.Content as TextBlock).TextWidth(); else if (cell.Content is TextBox) width = (cell.Content as TextBox).TextWidth(); if (cell.Content is FrameworkElement) { var widget = cell.Content as FrameworkElement; width = width + widget.Margin.Left + widget.Margin.Right; } max_widths[col] = Math.Max(max_widths[col], width*ugly_factor+cell.Padding.Left+cell.Padding.Right); } double width_diff = 0; foreach (var col in Enumerable.Range(0, dataGrid.Columns.Count)) width_diff += Math.Max(0,max_widths[col] - dataGrid.Columns[col].ActualWidth); if (width_diff > 0) window.Width = window.ActualWidth+ width_diff; } 

我刚刚出现了同样的问题,我必须在数据网格的列中提供选项,以根据标题和单元格的内容来适应其宽度。 我使用了以下代码:

 private void FitToContent() { // where dg is my data grid's name... foreach (DataGridColumn column in dg.Columns) { //if you want to size ur column as per the cell content column.Width = new DataGridLength(1.0, DataGridLengthUnitType.SizeToCells); //if you want to size ur column as per the column header column.Width = new DataGridLength(1.0, DataGridLengthUnitType.SizeToHeader); //if you want to size ur column as per both header and cell content column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto); } } 

我还根据显示(datagrid的宽度)提供了一个适合列的选项。 为此,我使用上面相同的代码进行以下微小更改:

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

FOR ALL COLUMNS …. :)确保将Horizo​​ntalScrollVisibility保持为Auto。

如果我理解你的问题,你想:

  1. 一个DataGrid,其中列的宽度与其最宽的内容一样宽。
  2. DataGrid适合其内容。

这可以通过数据绑定来实现:

       

这里第一列是需要宽的,第二列是剩下的扩展空间。 然而,DataGrid的宽度与Grid的widht相同,因此实现了所需的结果。

SizeToCells对我有用。 我喜欢这个,因为它在XAML中并且简洁。

  

Marko的评论是答案:

你的resize逻辑让我有点失落。 首先,如果设置窗口的SizeToContent="WidthAndHeight" ,则窗口将显示为datagrid的完整大小。 另一方面,如果您显示某个预定义大小的窗口,并且您希望在显示窗口后调整窗口大小,那么此时resize到所需的数据网格是非常反直觉的。 因为resize会从100px跳到400px,但如果我想resize只有250px …(假设你通过拖动窗口的角落resize)

在我的情况下,我发现DataGrid默认使用HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ,所以我将它设置为

  

然后工作。