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

132

我正在为Windows窗体(C# 2.0,非WPF)填充DataGridView控件。

我的目标是显示一个网格,它可以整齐地填满所有可用的宽度,没有未使用的区域(深灰色),并根据数据内容适当调整每个列的大小,但也允许用户调整任何列以适应他们的需要。

我试图通过将每个列的AutoSizeMode设置为DataGridViewAutoSizeColumnMode.AllCells,除了其中一个列,我将其设置为DataGridViewAutoSizeColumnMode.Fill,以确保网格的整个区域都可以装下数据。 (当用户尝试调整此列大小时,它会弹回到确保始终使用水平空间的大小,这一点我不介意。)

然而,正如我之前提到的那样,加载后我想允许用户调整列以适应他们自己的要求-在为每个列设置这些AutoSizeMode值时,似乎用户无法调整这些列的大小。

我尝试过不设置所有列的AutoSizeMode值,这样可以允许调整大小,但是无法根据单元格包含的数据设置初始大小。当更改网格的AutoSizeMode回到“未设置”状态以加载数据后,结果相同。

是否有我错过的设置,可以同时实现默认列宽的自动设置和用户调整大小,或者在填充DataGridView控件时必须使用其他技术?


不要将其设置为“未设置”,而应将其设置为“无”,以便调整大小不会恢复--已在C#、.NET2.0中进行测试。 - bh_earth0
25个回答

165

这个技巧对我有用:

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

在上面的代码中: 您将列AutoSize属性设置为所需的任何AutoSizeMode。 然后(逐列),您存储每个列宽度值(从AutoSize值); 禁用AutoSize属性,最后将列宽度设置为先前存储的宽度值。


2
我将类似的代码放在一个名为AutoResizeColumnWidthsYetAllowUserResizing的例程中。它在网格最初填充后以及用户编辑数据后(即从网格的CellEndEdit事件)被调用。 - DeveloperDan
7
这是很棒的代码。需要将其放置在“DataGridView1_DataSourceChanged”事件中。 - user890332
1
在我看来,执行 grd.Columns(i).Width = grd.Columns(i).Width 就已经可以解决问题了。请参见这里 - Antonio
2
对于C#,类似但使用方括号的代码是 dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; - barlop
1
根据这个答案和其他建议,我将代码简化为以下内容:`private void AutoSizeGridColumns(DataGridView grd) { //将自动调整大小设置为填充单元格内容 for (int i = 0; i <= grd.Columns.Count - 1; i++) { grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; grd.Columns[i].Width = grd.Columns[i].Width; //这样可以使宽度可由用户调整,因为AllCells会锁定它 } }` - kuklei
显示剩余2条评论

52

2
我不确定为什么这个答案没有引起更多的注意。 更干净。 虽然如果你想匹配DataGridView中单元格内容的宽度,DataGridViewAutoSizeColumnsMode.AllCells效果会更好一些。 - iwalkbarefoot
40
使用这个解决方案时,我遇到了下一个错误:“参数autoSizeColumnMode对于此操作无效。它不能是NotSet、None或Fill,而需要指定一个调整大小的标准。”最终我使用了这个代码:dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill; - itsho
6
使用DataGridViewAutoSizeColumnMode.Fill无法起作用,因为它在调整列宽时会忽略单元格内容。 - Stuart Helwig
2
我使用了DataGridViewAutoSizeColumnsMode.DisplayedCells这个方法。此外,在表单设计器中,AutoSizeColumnsMode设置为None。我需要在DataGridView的DataBindingComplete事件处理程序中执行此方法调用,以确保它始终正确地调整大小。 - Daan
9
我不明白所有的赞是为什么... 这根本行不通,MSDN文档很清楚,如果autoSizeColumnsMode的值为None或Fill,则这样做会导致ArgumentException。 - Larry
显示剩余5条评论

34

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

发布为社区维基,以避免依赖他人的声望


22
在我的应用程序中,我已经设置了
grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
grid.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;

另外,我已经设置了

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

现在用户可以更改列宽并重新排列列。这对我来说运作得非常好。

也许这对你也有用。


将网格的AutoSizeColumnsMode设置为“Fill”似乎会将所有列设置为相同的宽度。是的,列现在可以调整大小,但初始宽度都是错误的。我可能需要在代码中“手动”设置列宽度。 - Stuart Helwig
DV-grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.Fill;(你错过了s,左右两侧都是ColumsMode,所以你的那行代码无法编译)获取datagridview自动调整大小的代码非常恼人,因此请先检查您的答案。这是您编写的第一行,是错误的。 - barlop
@barlop 感谢您的回复。您有编辑问题和答案的特权。如果您发现我的代码中有错误,请随意进行编辑。 - Jehof

19
在向网格添加数据后,请添加以下代码,该代码将根据每个单元格中数据的长度调整列宽。
在将数据添加到网格后,添加以下代码,可以根据每个单元格中的数据长度来调整列宽。
dataGrid1.AutoResizeColumns();            
dataGrid1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;

这里是结果

输入图像描述


1
运行得像魔法一样。 - Umair

11

我是这样做的:

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

按照特定的顺序。列被调整大小(扩展),用户随后可以调整列的大小。


11

我用了简单的两行代码。

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

6
如果我理解问题正确,那么有一种更简单的方法可以实现您所需的功能。调用dgvSomeDataGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);。这应该就可以了。但是,有一个陷阱,您不能在填充DataGridView控件后直接调用此方法。相反,您需要为VisibleChanged事件添加一个EventHandler,在其中调用该方法。

1
这将根据内容调整列的大小,但不能确保使用所有可用的网格空间。也就是说,如果有剩余空间,它不会“填充”该空间。 - Stuart Helwig

5

问题简述:
需要让列宽随内容自适应(但是使用不同的方法在各个列之间),
然后允许用户设置列宽...

根据Miroslav Zadravec的回答,我开发时采用的方法是立即使用自动计算的 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

经过测试,当DataGridView已经创建时,可以使用类似这样的技巧来使其正常工作。


我更喜欢使用foreach,就像你的代码一样。当循环顶部没有任何数学计算时,它使得代码更易读。我也是这样做的,“column.Width = column.Width;”这句话很有趣。 - Greg Barth

4
这对我非常有帮助:

这对我产生了奇妙的效果:

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);

1
简单的解决方案! - Mark Kram
1
只有在设置为None之后才对我起作用,即 dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; - Do-do-new

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接