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


109

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

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

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

但是,正如我提到的,加载后,我希望允许用户调整列的大小以适合自己的需求-在为每个列设置这些AutoSizeMode值时,用户似乎无法再调整这些列的大小。

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

是否缺少我可以自动设置默认列宽和用户调整大小的设置,还是在填充DataGridView控件时必须使用另一种技术?


不要将其设置为“未设置”,将其设置为“无”, 这样调整大小就不会恢复 原状

Answers:


132

这个技巧对我有用:

grd.DataSource = DT;

//set autosize mode
grd.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
grd.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

//datagrid has calculated it's widths so we can store them
for (int i = 0; i <= grd.Columns.Count - 1; i++) {
    //store autosized widths
    int colw = grd.Columns[i].Width;
    //remove autosizing
    grd.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
    //set width to calculated by autosize
    grd.Columns[i].Width = colw;
}

这里发生的事情是,将自动调整大小设置为所需的任何模式,然后逐列存储自动调整大小得到的宽度,删除自动调整大小并将宽度设置为之前存储的值。


1
我将类似的代码放在名为AutoResizeColumnWidthsYetAllowUserResizing的例程中。在最初填充网格之后以及用户编辑数据之后(即,从网格的CellEndEdit事件中),都将调用它。
DeveloperDan 2010年

5
这是很棒的代码。需要放在“ DataGridView1_DataSourceChanged”事件中。
user890332 '02

1
在我看来,这样做grd.Columns(i).Width = grd.Columns(i).Width已经可以解决问题。看这里
安东尼奥

2
对于c#类似,但带有方括号 dataGridView1.Columns[i].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
barlop

这可能来得太晚了,但是有没有机会或方式,我们可以根据特定行的内容来调整大小?可以说,基于第一行中单元格的内容,而不考虑其他行中单元格的宽度吗?
Murtuza Husain

45

也许你可以打电话

dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.Fill);

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

有关MSDN DataGridView.AutoResizeColumns方法(DataGridViewAutoSizeColumnsMode)的更多信息


2
我不确定为什么这个答案没有得到更多的关注。干净得多。虽然如果您要匹配单元格内容的宽度,DataGridViewAutoSizeColumnsMode.AllCells的效果会更好一些。
iwalkbarefoot

31
使用此解决方案时,我会遇到下一个错误:“参数autoSizeColumnMode对此操作无效。它不能为NotSet,None或Fill,但需要指示尺寸调整标准。” 。我最终使用了此dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
itsho 2012年

6
使用DataGridViewAutoSizeColumnMode.Fill不起作用,因为它在调整列大小时会忽略单元格内容。
Stuart Helwig

我已将此方法用于DataGridViewAutoSizeColumnsMode.DisplayedCells。此外,在窗体设计器中,AutoSizeColumnsMode设置为None。我需要在DataGridView的DataBindingComplete事件处理程序中执行此方法调用,以确保其大小总是正确(重新)。
大安2014年

7
我不理解所有支持...这根本不起作用,MSDN文档很清楚,如果autoSizeColumnsMode的值为None或Fill,则这样做会导致ArgumentException。
拉里

31

Miroslav Zadravec的代码的AC#版本

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,以免影响他人的声誉


15

在我的应用程序中,我已设置

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

另外,我设置了

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

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

也许对您有用。


将网格的AutoSizeColumnsMode设置为“ Fill”似乎会将所有列设置为相同的宽度。是的,然后可以调整列的大小,但是初始宽度全都错了。我可能需要在代码中“手动”设置列宽。
Stuart Helwig 2009年

DV- grid.AutoSizeColumnsMode = DataGridViewAutoSizeColumn-> s <-Mode.Fill; (您错过了s,它在左侧和右侧是ColumsMode,因此您的那一行不会编译)使datagridview自动调整大小的代码非常令人讨厌,因此至少请首先检查您的答案。这是您写的第一行,而且是错误的。
barlop

@barlop感谢您的回复。您具有编辑问题和答案的权限。如果您发现我的代码有误,请随时进行编辑。
Jehof

12

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

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

这是结果

在此处输入图片说明


9

好吧,我这样做是这样的:

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

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


6

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

这应该够了吧。但是,存在一个陷阱,因为您不能在填充DataGridView控件后直接简单地调用此方法。相反,您将必须为VisibleChanged事件添加一个EventHandler并在其中调用该方法。


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


4

问题的继续:使
列宽适应内容(跨列使用不同的方法),
但是然后允许用户设置列宽...

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
简单的解决方案!
马克·克拉姆'18

1
仅在之后设置为None时为我工作,例如dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells); dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
Do-do-new

3

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

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

我知道这是一个老答案,但是即使事先不知道列数,我也能很好地工作。
尼洛·派姆

2

假设所有列都将自动调整大小,那么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;
}

2

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了表单的初始化,并且如果两个部分都在那里,则什么都没有改变,因为可能在datagridview显示后自动调整大小会计算宽度,因此该宽度仍然是Form1()方法中的默认值。完成此方法后,自动调整大小就可以解决问题,并且在此之后立即显示格式时,我们可以通过代码的第二部分设置宽度(Form1Shown以防万一)。这对我来说就像是魅​​力。


2

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


1

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


1

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

第一步 :

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

1
foreach (DataGridViewColumn c in dataGridView.Columns)
    c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);

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

由于DataGridViewAutoSizeColumnMode.DisplayedCells明显的原因,在上述情况下,使用相同的方法会失败,因为-尚未显示任何单元格!由于某些非显而易见的原因,AutoResizeColumns在这种情况下也会失败。


0

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

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

0
  • 感谢上述解决方案(要遍历DataGridView.Columns,更改AutoSizeMode为有效值,请收集宽度值,然后将其更改AutoSizeModeDataGridViewAutoSizeColumnMode.None)。
  • 我与它挣扎着,并注意到每当它是从类的构造函数或之前的任何行调用它不会工作Form.Show()Form.ShowDialog()。因此,我将此代码段放入Form.Shown事件中,这对我有用。
  • 我转换后的代码,不管DataGridView.AutoSizeColumnsMode之前的设置如何,我都使用,DataGridViewColumn.GetPreferredWidth()而不是DataGridViewColumn.AutoSizeMode立即更改并设置width值,然后更改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;
  • 我不知道为什么只有在显示表格后才能起作用。


0

我必须在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

0

您可以执行以下操作:

   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;

所有列将适应内容,最后一行将填充网格。


0

使用$ array作为PSCustomObject的内容,可以使用:

$dataGridView1.DataSource=[collections.arraylist]($array)
$dataGridView1.Columns | Foreach-Object{$_.AutoSizeMode = [System.Windows.Forms.DataGridViewAutoSizeColumnMode]::AllCells}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.