【问题标题】:How do you automatically resize columns in a DataGridView control AND allow the user to resize the columns on that same grid?如何自动调整 DataGridView 控件中的列大小并允许用户调整同一网格上的列大小?
【发布时间】:2010-11-04 18:28:45
【问题描述】:

我正在 Windows 窗体上填充 DataGridView 控件(C# 2.0 不是 WPF)。

我的目标是显示一个网格,用单元格整齐地填充所有可用宽度 - 即右侧没有未使用的(深灰色)区域,并根据其包含的数据适当调整每列的大小,但是还允许用户根据自己的喜好调整任何列的大小。

我试图通过将每列的 AutoSizeMode 设置为 DataGridViewAutoSizeColumnMode.AllCells 来实现此目的,除了我按顺序设置为 DataGridViewAutoSizeColumnMode.Fill 的列之一以确保网格的整个区域都整齐地填充数据。 (我不介意当用户尝试调整此列的大小时,它会弹回确保始终使用水平空间的大小。)

但是,正如我所提到的,一旦加载,我希望允许用户调整列的大小以满足他们自己的要求 - 在为每一列设置这些 AutoSizeMode 值时,用户似乎无法再调整这些列的大小。

我尝试不设置允许调整大小的所有列的 AutoSizeMode,但不会根据单元格包含的数据设置初始大小。加载数据后将网格的 AutoSizeMode 更改回“未设置”时,也会出现相同的结果。

我在这里是否缺少允许自动设置默认列宽和用户调整大小的设置,或者在填充 DataGridView 控件时我必须使用其他技术吗?

【问题讨论】:

  • 不要将其设置为“未设置”,将其设置为 “无” 以便调整大小 不会恢复返回 - 已针对 c# 、 . net2.0

标签: c# winforms datagridview


【解决方案1】:

这个技巧对我有用:

    grd.DataSource = DT;

    // Set your desired AutoSize Mode:
    grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    grd.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    grd.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

    // Now that DataGridView has calculated it's Widths; we can now store each column Width values.
    for (int i = 0; i <= grd.Columns.Count - 1; i++)
    {
        // Store Auto Sized Widths:
        int colw = grd.Columns[i].Width;

        // Remove AutoSizing:
        grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

        // Set Width to calculated AutoSize value:
        grd.Columns[i].Width = colw;
    }

在上面的代码中: 您将 Columns AutoSize 属性设置为您需要的任何 AutoSizeMode。 然后(逐列)存储每列的宽度值(来自 AutoSize 值); 禁用 AutoSize 属性,最后将 Column Width 设置为您之前存储的 Width 值。

【讨论】:

  • 我将类似的代码放在名为 AutoResizeColumnWidthsYetAllowUserResizing 的例程中。在最初填充网格后以及用户编辑数据(即,从网格的 CellEndEdit 事件)之后调用它。
  • 这是很棒的代码。需要放入 'DataGridView1_DataSourceChanged' 事件中。
  • 在我看来,grd.Columns(i).Width = grd.Columns(i).Width 已经成功了。见here
  • 对于 c# 类似但带有方括号 dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
  • 这可能来得很晚,但是有什么机会或方式,我们可以根据特定行的内容调整大小吗?比方说,基于第一行中单元格的内容,而不考虑其他行中单元格的宽度?
【解决方案2】:

也许你可以打电话

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

设置数据源后。它将设置宽度并允许调整大小。

更多关于 MSDN DataGridView.AutoResizeColumns Method (DataGridViewAutoSizeColumnsMode).

【讨论】:

  • 我不确定为什么这个答案没有得到更多关注。干净多了。虽然如果您希望匹配单元格内容宽度 DataGridViewAutoSizeColumnsMode.AllCells 会更好一些。
  • 使用这个解决方案我得到下一个错误:“参数 autoSizeColumnMode 对这个操作无效。它不能是 NotSet、None 或 Fill,但需要指明一个大小标准。”。我最终使用了这个 dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
  • 使用 DataGridViewAutoSizeColumnMode.Fill 不起作用,因为它在调整列大小时会忽略单元格内容。
  • 我在DataGridViewAutoSizeColumnsMode.DisplayedCells 中使用过这种方法。此外,在窗体设计器中,AutoSizeColumnsMode 设置为 None。我需要在 DataGridView 的 DataBindingComplete 事件处理程序中执行此方法调用,以确保它始终(重新)正确调整大小。
  • 我不明白所有的赞成票...这根本不起作用,MSDN documentation 很清楚,如果 autoSizeColumnsMode 的值为 None 或 Fill,这样做会导致 ArgumentException。
【解决方案3】:

Miroslav Zadravec 代码的 C# 版本

for (int i = 0; i < dataGridView1.Columns.Count-1; i++)
{
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
dataGridView1.Columns[dataGridView1.Columns.Count - 1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
    int colw = dataGridView1.Columns[i].Width;
    dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    dataGridView1.Columns[i].Width = colw;
}

发布为社区 Wiki,以免影响他人的声誉

【讨论】:

    【解决方案4】:

    在我的应用程序中我设置了

    grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
    grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;
    

    另外,我设置了

    grid.AllowUserToOrderColumns = true;
    grid.AllowUserToResizeColumns = true;
    

    现在可以更改列宽,并且可以由用户重新排列列。这对我来说效果很好。

    也许这对你有用。

    【讨论】:

    • 将网格的 AutoSizeColumnsMode 设置为“Fill”似乎会将所有列设置为相同的宽度。是的,列然后可以调整大小,但初始宽度都是错误的。我可能需要“手动”在代码中设置列宽。
    • DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s
    • @barlop 感谢您的回复。您有权编辑问题和答案。如果您在我的代码中发现错误,请随时编辑。
    【解决方案5】:

    将数据添加到网格后,添加以下代码,它将根据每个单元格中数据的长度调整列

    dataGrid1.AutoResizeColumns();            
    dataGrid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
    

    这是结果

    【讨论】:

    • 像魅力一样工作
    【解决方案6】:

    嗯,我是这样做的:

    dgvReport.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    dgvReport.AutoResizeColumns();
    dgvReport.AllowUserToResizeColumns = true;
    dgvReport.AllowUserToOrderColumns = true;
    

    按特定顺序。列被调整大小(扩展)并且用户可以在之后调整列大小。

    【讨论】:

      【解决方案7】:

      简单的两行代码对我有用。

      dataGridView.DataSource = dataTable;
      dataGridView.AutoResizeColumns();
      

      【讨论】:

        【解决方案8】:

        如果我正确理解了这个问题,那么应该有一种更简单的方法来完成您所需要的。称呼 dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

        这应该可以解决问题。但是,存在一个缺陷,因为您不能在填充 DataGridView 控件后直接调用此方法。相反,您必须为 VisibleChanged 事件添加一个 EventHandler 并在其中调用该方法。

        【讨论】:

        • 这将根据内容调整列的大小,但不能确保使用所有可用的网格空间。即,如果有任何剩余空间,则不会“填充”剩余空间。
        【解决方案9】:

        问题简历:
        让列宽适应内容(跨列使用不同的方法),
        但随后允许用户设置列宽...

        Miroslav Zadravec's answer 开发,对我来说有效的是立即使用自动计算的column.Width 设置...column.Width

        foreach (DataGridViewColumn column in dataGridView.Columns)
        {
            if (/*It's not your special column*/)
            {
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                column.Width = column.Width; //This is important, otherwise the following line will nullify your previous command
                column.AutoSizeMode = DataGridViewAutoSizeColumnMode.NotSet;
            }
        }
        
        //Now do the same using Fill instead of AllCells for your special column
        

        使用this 之类的技巧,在已经创建DataGridView 时测试它可以工作。

        【讨论】:

        • 我更喜欢像您的代码那样使用 foreach。当您在循环顶部没有任何数学运算时,它使其更具可读性。我是这样做的,“column.Width = column.Width;”很有趣。
        【解决方案10】:

        这对我来说很神奇:

        dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        

        【讨论】:

        • 简单的解决方案!
        • 只有在之后设置为无时才为我工作,即dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
        【解决方案11】:

        这会根据其内容自动调整所有列,通过拉伸指定的列来填充剩余的空白空间,并通过设置最后一列来填充以供将来调整大小来防止“跳跃”行为。

        // autosize all columns according to their content
        dgv.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        // make column 1 (or whatever) fill the empty space
        dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        // remove column 1 autosizing to prevent 'jumping' behaviour
        dgv.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
        // let the last column fill the empty space when the grid or any column is resized (more natural/expected behaviour) 
        dgv.Columns.GetLastColumn(DataGridViewElementStates.None, DataGridViewElementStates.None).AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        

        【讨论】:

        • 我知道这是一个旧答案,但我工作得很好,即使事先不知道列数。
        【解决方案12】:

        Miroslav Zadravec 的代码中稍微简洁的 C# 代码,假设所有列都是自动调整大小的

        for (int i = 0; i < dgvProblems.Columns.Count; i++)
        {
            dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
            int colw = dgvProblems.Columns[i].Width;
            dgvProblems.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
            dgvProblems.Columns[i].Width = colw;
        }
        

        【讨论】:

          【解决方案13】:

          dataGridView1.AutoResizeColumns();

          【讨论】:

            【解决方案14】:

            另一个版本的 Miroslav Zadravec 的代码,但更自动化和通用:

                public Form1()
                {
                    InitializeComponent();
                    dataGridView1.DataSource = source;
                    for (int i = 0; i < dataGridView1.Columns.Count - 1; i++) {
                        dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                    }
                    dataGridView1.Columns[dataGridView1.Columns.Count].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
            
                }
            
                void Form1Shown(object sender, EventArgs e)
                {
                    for ( int i = 0; i < dataGridView1.Columns.Count; i++ )
                    {
                        int colw = dataGridView1.Columns[i].Width;
                        dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                        dataGridView1.Columns[i].Width = colw;
                    }
                }
            

            我将第二部分放入单独的事件中,因为我在表单的初始化中填写了datagridvew,如果两个部分都存在,则没有任何变化,因为可能 autosize 在显示datagridview 后计算宽度,所以宽度仍然是默认值在Form1() 方法中。完成此方法后,autosize 会发挥作用,然后立即(当显示表单时)我们可以通过代码的第二部分设置宽度(在Form1Shown 事件中)。这对我来说就像一个魅力。

            【讨论】:

              【解决方案15】:

              这是 Miroslav Zadravec 在 c# 中的回答的简化代码:

              CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader;
              for (int i = 0; i < dataGridView1.Columns.Count; i++) dataGridView1.Columns[i].Width = dataGridView1.Columns[i].Width;
              CurrentDGV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
              

              【讨论】:

                【解决方案16】:

                您是否尝试设置DataGridViewColumns 对象的FillWeight 属性?

                例如:

                this.grid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
                this.grid1.Columns[0].FillWeight = 1.5;
                

                我认为它应该适用于你的情况。

                【讨论】:

                  【解决方案17】:

                  比 Schnapple 的版本稍有改进

                  int nLastColumn = dgv.Columns.Count - 1;
                  for (int i = 0; i < dgv.Columns.Count; i++)
                  {
                      if (nLastColumn == i)
                      {
                          dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                      }
                      else
                      {
                          dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                      }
                  }
                  
                  for (int i = 0; i < dgv.Columns.Count; i++)
                  {
                      int colw = dgv.Columns[i].Width;
                      dgv.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
                      dgv.Columns[i].Width = colw;
                  }
                  

                  【讨论】:

                    【解决方案18】:

                    设置为适合其内容的列宽我使用了下面的语句, 它解决了我的问题。

                    第一步:

                    RadGridViewName.AutoSize = true;
                    

                    第二步:

                    // This mode  fit in the header text and column data for all visible rows. 
                    this.grdSpec.MasterTemplate.BestFitColumns();
                    

                    第三步:

                    for (int i = 0; i < grdSpec.Columns.Count; i++) 
                    {
                        // The column width adjusts to fit the contents all cells in the control.
                        grdSpec.Columns[i].AutoSizeMode = BestFitColumnMode.AllCells; 
                    }
                    

                    【讨论】:

                      【解决方案19】:
                      foreach (DataGridViewColumn c in dataGridView.Columns)
                          c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);
                      

                      无论dataGridView 是否显示(即即使从类构造函数调用),这都应该有效。

                      同样的方法,但使用DataGridViewAutoSizeColumnMode.DisplayedCells,在上述情况下失败,原因很明显——还没有显示单元格!由于某些不明显的原因,AutoResizeColumns 在这种情况下也会失败。

                      【讨论】:

                        【解决方案20】:

                        例如,如果您将数据源绑定到数据表,则需要在绑定完成后设置属性:

                                private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
                                {
                                    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
                                    dgv.AutoResizeColumns();
                                    dgv.AllowUserToResizeColumns = true;
                                }
                        

                        【讨论】:

                          【解决方案21】:
                          • 感谢上述解决方案(要遍历DataGridView.Columns,将AutoSizeMode 更改为有效值,收集宽度值并在将AutoSizeMode 更改为DataGridViewAutoSizeColumnMode.None 后将其设置回来)。
                          • 我一直在努力解决它,并注意到无论何时从类构造函数或Form.Show()Form.ShowDialog() 之前的任何行调用它都不起作用。所以我把这段代码 sn-p 放在Form.Shown 事件中,这对我有用。
                          • 我转换后的代码,不管DataGridView.AutoSizeColumnsMode之前设置了什么,我使用DataGridViewColumn.GetPreferredWidth()而不是更改DataGridViewColumn.AutoSizeMode并立即设置宽度值,然后更改DataGridView.AutoSizeColumnsMode一次:

                            private void form_Shown(object sender, EventArgs e)
                            {
                                    foreach (DataGridViewColumn c in dataGridView.Columns)
                                        c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.DisplayedCells, true);
                                    dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
                            }
                            
                          • 一定要设置

                                    dataGridView.AllowUserToResizeColumns = true;
                            
                          • 我不知道为什么这只有在显示表单后才有效。

                          【讨论】:

                            【解决方案22】:

                            我必须在 VB 中执行此操作,并且更愿意将其拆分为我放置在模块中的方法。如果需要,您可以将 Fill 列添加为另一个 ByRef 参数。

                            ''' <summary>
                            ''' Makes all columns in a DataGridView autosize based on displayed cells,
                            ''' while leaving the column widths user-adjustable.
                            ''' </summary>
                            ''' <param name="dgv">A DataGridView to adjust</param>
                            Friend Sub MakeAdjustableAutoSizedGridCols(ByRef dgv As DataGridView)
                                Dim width As Integer
                            
                                For Each col As DataGridViewColumn In dgv.Columns
                                    col.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
                                    width = col.Width
                                    col.AutoSizeMode = DataGridViewAutoSizeColumnMode.None
                                    col.Width = width
                                Next
                                dgv.AllowUserToResizeColumns = True
                            End Sub
                            

                            【讨论】:

                              【解决方案23】:

                              你可以这样做:

                                 grd.DataSource = getDataSource();
                              
                                  if (grd.ColumnCount > 1)
                                  {
                                      for (int i = 0; i < grd.ColumnCount-1; i++)
                                          grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                              
                                      grd.Columns[grd.ColumnCount-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                                  }
                              
                                  if (grd.ColumnCount==1)
                                      grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                              

                              所有列都将适应内容,除了最后一列将填满网格。

                              【讨论】:

                                【解决方案24】:

                                $array 是 PSCustomObject 的内容,这很有效:

                                $dataGridView1.DataSource=[collections.arraylist]($array)
                                $dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
                                

                                【讨论】:

                                  猜你喜欢
                                  • 2011-02-28
                                  • 1970-01-01
                                  • 1970-01-01
                                  • 2011-01-19
                                  • 2014-03-21
                                  • 2012-07-03
                                  • 2012-12-22
                                  • 2012-01-01
                                  • 1970-01-01
                                  相关资源
                                  最近更新 更多