如何自动调整 DataGridView 控件中的列大小并允许用户调整同一网格上的列大小?

Posted

技术标签:

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

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

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

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

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

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

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

【问题讨论】:

不要将其设置为“未设置”,将其设置为 “无” 以便调整大小 不会恢复返回 - 已针对 c# 、 . net2.0 【参考方案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

【讨论】:

以上是关于如何自动调整 DataGridView 控件中的列大小并允许用户调整同一网格上的列大小?的主要内容,如果未能解决你的问题,请参考以下文章

如何在窗体调整大小时调整datagridview控件的大小

c#winfrom中datagridview控件如何自定义一个datagridview的列。主要是想实现类似EXCEL中的合并单元格

如何实现dataGridView中点击某个单元后,自动选中整列

如何禁止datagridview列顺序自动改变位置

c# datagridview 根据内容自动调整行高

如何在C#中 禁止 dataGridView 自动添加行