自动调整和填充DataGridView

109

我在我的DataGridView中有3列。我想要做的是让前两列自适应内容的宽度,第三列填满剩余空间。

在WinForms中是否有可能实现?如果有用的话,我的数据是从EF DataContext中加载的。我已经包含了当前显示状态的图片。

输入图像描述

10个回答

201

您需要使用 DataGridViewColumn.AutoSizeMode 属性。

对于第0列和第1列,您可以使用以下值:

AllCells: 列宽度根据列中所有单元格(包括标题单元格)的内容调整。
AllCellsExceptHeader: 列宽度根据列中除标题单元格以外的所有单元格的内容调整。
DisplayedCells: 列宽度根据列中当前在屏幕上显示的所有行中的所有单元格的内容调整(包括标题单元格)。
DisplayedCellsExceptHeader: 列宽度根据列中当前在屏幕上显示的除标题单元格以外的所有行中的所有单元格的内容调整。

然后对于第2列,您需要使用 Fill

列宽度调整为所有列的宽度恰好填充控件的显示区域...

this.DataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
this.DataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
this.DataGridView1.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

正如其他用户所指出的,可以使用DataGridView.AutoSizeColumnsMode属性在datagridview级别上设置默认值。

this.DataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
this.DataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;

可能是:

this.DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;

重要提示:

如果您的网格绑定到数据源并且列是自动生成的(AutoGenerateColumns 属性设置为 True),则需要在列创建完成 之后 使用 DataBindingComplete 事件应用样式。


在某些情况下(例如通过代码更改单元格值),我必须调用 DataGridView1.AutoResizeColumns(); 来刷新网格。


2
使用DataBindingComplete事件时完美运作。 - James Jeffery
我无法弄清如何在数据网格填充后调用DataBindingComplete方法。 - Dan
@Dan DataBindingComplete不是一个方法,而是一个datagridview 事件,您需要订阅它。这个答案https://dev59.com/z2Ml5IYBdhLWcg3wJD5S#31685874给出了一个例子。它有帮助吗? - Chris
如果能够解释一下示例就更好了,但这样也可以。你在帖子中提供的MSDN文章链接将其显示为一个方法,这也是我用作模式的内容,但我无法弄清它是如何被调用的。 - Dan
@Dan 是的,MSDN的示例展示了使用这个特定事件的方法。我以为你已经知道如何在.Net中使用事件了。如果需要的话,你可以阅读这篇文章,它涉及到事件。有很多方法可以引发它们。 - Chris
1
@Chris,缺失的信息确实很有帮助,谢谢。我正在阅读《这本书》(https://www.amazon.com/C-6-0-NET-4-6-Framework-ebook/dp/B015XFLAF0),刚刚到达有关委托和 Lambda 函数的章节,希望不久后能更好地理解它们。谢谢! - Dan

25

这是我最喜欢的方法...

_dataGrid.DataBindingComplete += (o, _) =>
    {
        var dataGridView = o as DataGridView;
        if (dataGridView != null)
        {
           dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
           dataGridView.Columns[dataGridView.ColumnCount-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
        }
    };

1
如果列大小为0,则只需修复“索引越界异常”,谢谢! - TiyebM

19

只需更改控件的属性即可: AutoSizeColumnsMode:Fill

或者通过代码实现

dataGridView1.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.Fill;


1
谢谢。我一直在寻找这样的解决方案! :) - Alin Ciocan

6

没有经过测试,但您可以尝试一下。已测试并且可行。我希望您可以尝试使用DataGridViewColumnAutoSizeMode来实现您的需求。

尝试设置

dataGridView1.DataSource = yourdatasource;<--set datasource before you set AutoSizeMode

//Set the following properties after setting datasource
dataGridView1.Columns[0].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView1.Columns[1].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
dataGridView1.Columns[2].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;

这应该可以工作。

这个不起作用。我是在表单初始化时设置它的,此时数据源还未从 DataContext 添加。这可能是原因吗?我不确定在哪里设置它,因为数据是在运行时加载的,并且列是从 EF 模型中获取的。 - James Jeffery
看起来是那样,但实际上不是,第三行代码有问题,我在10分钟前测试过了。 - King King
@JamesJeffery 你是自动填充列还是手动填充的? - Sriram Sakthivel
@SriramSakthivel 我正在使用dataGridView1.DataSource属性来绑定从我的DataContext返回的List。 - James Jeffery

2

试着去做,

 AutoSizeColumnMode = Fill;

将以下语句翻译成中文:dataGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill。请只返回翻译后的文本内容,不要进行解释。 - undefined

2

为了让“first_name”列在其他列无法填充空间时也能填充,我所做的是:

当网格变得很小时,“first_name”列几乎看不见(非常细),因此我可以将 DataGridViewAutoSizeColumnMode 属性设置为AllCells,就像其他可见列一样。出于性能考虑,在数据绑定之前需要将它们设置为 None,并在网格的 DataBindingComplete 事件处理程序中设置回 AllCells。希望这会有所帮助!

private void dataGridView1_Resize(object sender, EventArgs e)
{
    int ColumnsWidth = 0;
    foreach(DataGridViewColumn col in dataGridView1.Columns)
    {
        if (col.Visible) ColumnsWidth += col.Width;
    }
    if (ColumnsWidth <dataGridView1.Width)
    {
        dataGridView1.Columns["first_name"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
    }
    else if (dataGridView1.Columns["first_name"].Width < 10) 
    {
        dataGridView1.Columns["first_name"].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
    }
}

0
public static void Fill(DataGridView dgv2)
   {
        try
        {
            dgv = dgv2;
            foreach (DataGridViewColumn GridCol in dgv.Columns)
            {
                for (int j = 0; j < GridCol.DataGridView.ColumnCount; j++)
                {
                    GridCol.DataGridView.Columns[j].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
                    GridCol.DataGridView.Columns[j].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
                    GridCol.DataGridView.Columns[j].FillWeight = 1;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

1
这段代码不太好。首先,你不需要嵌套循环,它会多次设置所有列的宽度模式为相同的值(<列数>次)。你可以直接从GridCol访问每个列的AutoSizeModeFillWeight属性。其次,它将每个列的AutoSizeMode设置为两个不同的值;第二个赋值将覆盖第一个。 - JonP

0
继承AlfredBr的答案,如果您隐藏了某些列,您可以使用以下方法自动调整所有列的大小,然后只需将最后一个可见列填充空白空间即可:
myDgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
myDgv.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None).AutoSizeMode = 
    DataGridViewAutoSizeColumnMode.Fill;

-1
public void setHeight(DataGridView src)
{
    src.Height= src.ColumnHeadersVisible ? src.ColumnHeadersHeight : 0 +   src.Rows.OfType<DataGridViewRow>().Where(row => row.Visible).Sum(row => row.Height);
}

只需调用该函数,它会根据其中的行数决定 datagridview 的高度。 - Durga Prasad Guntoju
1
首先,那并没有回答问题。另外(作为将来的参考),请在答案本身中包含这样的评论(您可以编辑它)。 - Joel

-2

试试这个:

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

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