如何自动调整 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 控件中的列大小并允许用户调整同一网格上的列大小?的主要内容,如果未能解决你的问题,请参考以下文章
c#winfrom中datagridview控件如何自定义一个datagridview的列。主要是想实现类似EXCEL中的合并单元格