如何调整WPF的DataGrid以适应其内容吗? [英] How to resize WPF DataGrid to fit its content?

查看:201
本文介绍了如何调整WPF的DataGrid以适应其内容吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标



我想为DataGrid(标准,从WPF)等设定大小,这样所有的细胞(文本)是完全可见。我有窗口DockPanel中,用的DataGrid中,所以当我调整窗口的大小,所有的嵌套小部件(DockPanel中和DataGrid)也相应调整。



示例(编辑-1)



假设你有窗口,100个像素宽,你必须DataGrid中有一列,其中电池是敏捷的棕色狐狸......(400像素宽)。因此,DataGrid中应调整为400像素(可能更多,因为填充)和窗口应该被调整到400像素太(也比较多,因为填充)。



我没有找到任何标准方法来做到这一点(据我所知WPF提供的方式来剪辑内容所需要的宽度,我的问题正好相反),所以我想出这么丑的解决方法,这并不太多工作好。



解决方法




  1. 遍历DataGrid中头文件(假设他们只是文本

  2. 必需的字符串),并计算宽度遍历DataGrid行每每列(假设他们的TextBlock或文本框),并计算文本所需的最大宽度 - 加垫的水平为的TextBlock /文本框和水平边距DataGrid单元格

  3. 总和的DataGrid ActualWidth的之间的列(2)
  4. 计算的最大宽度的所有分歧
  5. 增加由(3)中
  6. 计算出的差


    问题



    窗口宽度我做多次试验,并在某些情况下,所计算的宽度过大(这是小问题),对于某些情况下,过小。问题开始在其核心程序 - 计算为文本框/ TextBlock的所需宽度,计算宽度始终1单位小于它应该是(如果我将宽度设置为计算的一个,从文本1的象素总是被限幅)

    所以哪些因素我忽略这里或者,也许更好 - ?有已经调整大小DataGrid中以适合其内容的一些方法



    中的代码



    计算文本(此处为TextBlock的)要求的宽度:

     公共静态双重文本宽度(这TextBlock的小部件,字符串文本)
    {
    变种formattedText =新formattedText(文字,/ /可以用任意的文本
    System.Globalization.CultureInfo.CurrentCulture,
    widget.FlowDirection,
    widget.FontFamily.GetTypefaces()。FirstOrDefault(),
    widget.FontSize,
    widget.Foreground);

    返回formattedText.Width + widget.Padding.Left + widget.Padding.Right;
    }



    调整窗口大小以适合DataGrid的内容(ugly_factor是丑陋的解决办法;-)因为我没有弄清楚如何解决它正确我将它设置为1.3,并通过这种方式我的窗口是从不太小):

     公共静态无效AdjustWidthToDataGrid(此Window窗口,DataGrid的DataGrid后,双ugly_factor)
    {
    VAR max_widths = dataGrid.Columns.Select(IT = GT; window.TextWidth(it.Header作为字符串)
    * ugly_factor).ToArray();

    的foreach(在Enumerable.Range VAR行(0,dataGrid.Items.Count))
    的foreach(在Enumerable.Range VAR山坳(0,dataGrid.Columns.Count))
    {
    细胞无功= dataGrid.GetCell(行,列);
    双倍宽度= 0;
    如果(cell.Content是TextBlock的)
    宽度=(cell.Content作为TextBlock的).TextWidth();
    ,否则如果(cell.Content是文本框)
    宽度=(cell.Content为文本框).TextWidth();

    如果(cell.Content是FrameworkElement的)
    {
    VAR部件= cell.Content为FrameworkElement的;
    宽度=宽度+ widget.Margin.Left + widget.Margin.Right;
    }

    max_widths [COL] = Math.Max​​(max_widths [COL],
    宽* ugly_factor + cell.Padding.Left + cell.Padding.Right);
    }

    双width_diff = 0;

    的foreach(在Enumerable.Range VAR山坳(0,dataGrid.Columns.Count))
    width_diff + = Math.Max​​(0,max_widths [COL] - dataGrid.Columns [COL] .ActualWidth);

    如果(width_diff大于0)
    window.Width = window.ActualWidth + width_diff;
    }


    解决方案

    马尔科的评论是答案:




    我在一个位与尺寸调整逻辑的损失。首先,如果你设置窗口的 SizeToContent =WidthAndHeight,则该窗口显示为DataGrid的全尺寸。在另一方面,如果在一些预定义的大小显示一个窗口,并且要调整窗口一旦所示的窗口,然后在该点调整大小以期望与DataGrid的非常直觉。因为大小调整将从跳说100像素400像素,但如果我想调整到只有250像素...(asuming可以通过拖动窗口的一角调整)



    The aim

    I would like to set such size for the DataGrid (standard, from WPF) so all cells (text) would be fully visible. I have window with DockPanel, with DataGrid in it, so when I resize the window, all nested widgets (DockPanel and DataGrid) are resized accordingly.

    Example (edit-1)

    Let's say you have window, 100 pixels wide and you have DataGrid with one column, which cell is "the quick brown fox..." (400 pixels wide). Thus the DataGrid should be resized to 400 pixels (probably more, because of padding) and the Window should be resized to 400 pixels too (also more, because of padding).

    I didn't find any standard method to do it (AFAIK WPF provides way to clip the content to desired width, my problem is exactly opposite), so I come up with such ugly workaround, which does not work too well.

    The workaround

    1. iterate over DataGrid headers (assuming they are just strings) and compute width required for the text
    2. iterate over DataGrid rows per each column (assuming they are TextBlock or TextBox) and compute the maximum width required for the text -- add horizontal paddings for TextBlock/TextBox and horizontal margins for DataGrid cell
    3. sum all differences between DataGrid ActualWidth for columns and the maximum width computed in (2)
    4. increase the window width by the difference computed in (3)

    THE PROBLEM

    I did several tests, and in some cases the computed width is too big (this is minor problem), for some cases is too small. The problem starts at its core procedure -- computing the required width for TextBox/TextBlock, computed width is always 1 unit less than it should be (if I set the width to computed one, 1 pixel from text is always clipped).

    So which factor I am ignoring here? Or maybe better -- is there already some method to resize DataGrid to fit its content?

    The code

    Computing width required for text (here for 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;
        }
    

    Adjusting the Window size to fit DataGrid content (ugly_factor is ugly workaround ;-) since I didn't figure out how to fix it properly I set it to 1.3 and this way my window is "never" too small):

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

    解决方案

    Marko's comment is the answer:

    I'm at a bit of a loss with your resizing logic. First of all, if you set the window's SizeToContent="WidthAndHeight", then the window is shown to the full size of the datagrid. On the other hand, if you show a window at some predefined size, and you want to resize the window once the window is shown, then at that point resizing to the datagrid's desired with is very counter intuitive. Because the resizing will jump from say 100px to 400px, but what if I want to resize to only 250px... (asuming you resize by dragging the corner of the window)

    这篇关于如何调整WPF的DataGrid以适应其内容吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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