108

I have 3 columns in my DataGridView. What I am trying to do is have the first 2 columns auto fit to the width of the content, and have the 3rd column fill the remaining space.

Is it possible to do in WinForms? I am loading my data from an EF DataContext if that's any use. I have included an image of how it currently looks.

enter image description here

Chris
  • 8,527
  • 10
  • 34
  • 51
James Jeffery
  • 12,093
  • 19
  • 74
  • 108

10 Answers10

200

You need to use the DataGridViewColumn.AutoSizeMode property.

You can use one of these values for column 0 and 1:

AllCells: The column width adjusts to fit the contents of all cells in the column, including the header cell.
AllCellsExceptHeader: The column width adjusts to fit the contents of all cells in the column, excluding the header cell.
DisplayedCells: The column width adjusts to fit the contents of all cells in the column that are in rows currently displayed onscreen, including the header cell.
DisplayedCellsExceptHeader: The column width adjusts to fit the contents of all cells in the column that are in rows currently displayed onscreen, excluding the header cell.

Then you use the Fill value for column 2

The column width adjusts so that the widths of all columns exactly fills the display area of the control...

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

As pointed out by other users, the default value can be set at datagridview level with DataGridView.AutoSizeColumnsMode property.

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

could be:

this.DataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells;

Important note:

If your grid is bound to a datasource and columns are auto-generated (AutoGenerateColumns property set to True), you need to use the DataBindingComplete event to apply style AFTER columns have been created.


In some scenarios (change cells value by code for example), I had to call DataGridView1.AutoResizeColumns(); to refresh the grid.

Chris
  • 8,527
  • 10
  • 34
  • 51
  • 2
    Works perfectly when using the DataBindingComplete event. – James Jeffery Sep 06 '13 at 21:33
  • I can't figure how to call DataBindingComplete method after datagrid is populated – Dan Jul 06 '16 at 21:25
  • @Dan DataBindingComplete is not a *method*, it's an datagridview *event* to which you need to subscribe. This answer http://stackoverflow.com/a/31685874/2387010 gives an example. Does it helps? – Chris Jul 06 '16 at 22:27
  • It would be helpful if the example was explained, but will suffice. The [MSDN article that you linked to in your post](https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridview.databindingcomplete(v=vs.110).aspx) shows it as a method, which is what I used as my pattern but can't figure out how it gets called. – Dan Jul 06 '16 at 23:21
  • @Dan Yes, the MSDN example shows a method that use this specific event. I was thinking you already knew how to use events in .Net. If needed, you could read [this](https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx) that deals with events. There are many ways to raise them. – Chris Jul 06 '16 at 23:49
  • 1
    @Chris that piece of missing information is definitely helpful, thanks. I am reading [this book](https://www.amazon.com/C-6-0-NET-4-6-Framework-ebook/dp/B015XFLAF0) and *just* got to the chapter on delegates and lambda functions so this will hopefully make more sense shortly. Thank you! – Dan Jul 07 '16 at 02:52
25

This is my favorite approach...

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

Just change Property from property of control: AutoSizeColumnsMode:Fill

OR By code

dataGridView1.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.Fill;

Ahosan Karim Asik
  • 3,219
  • 1
  • 18
  • 27
6

Not tested but you can give a try. Tested and working. I hope you can play with AutoSizeMode of DataGridViewColum to achieve what you need.

Try setting

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;

This should work

Sriram Sakthivel
  • 72,067
  • 7
  • 111
  • 189
  • This doesn't work. I am setting it when the form initializes before the data source is added from the DataContext. Could that be why? I am not sure where to set it as the data is loaded at run time and the columns are taken from the EF model. – James Jeffery Sep 06 '13 at 21:23
  • Looks like that but not, the third line doesn't work, I tested this 10 minutes ago. – King King Sep 06 '13 at 21:23
  • @JamesJeffery you're AutoPopulating columns or manually populating? – Sriram Sakthivel Sep 06 '13 at 21:25
  • @SriramSakthivel I am using the dataGridView1.DataSource property to bind a List returned from my DataContext. – James Jeffery Sep 06 '13 at 21:30
2

This is what I have done in order to get the column "first_name" fill the space when all the columns cannot do it.

When the grid goes to small the column "first_name" gets almost invisible (very thin) so I can set the DataGridViewAutoSizeColumnMode property to AllCells as the others visible columns. For performance issues it's important to set them to None before data binding it and set back to AllCells in the DataBindingComplete event handler of the grid. Hope it helps!

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;
    }
}
Lemonseed
  • 1,644
  • 1
  • 15
  • 29
Ignacio
  • 910
  • 2
  • 12
  • 24
1

Try doing,

 AutoSizeColumnMode = Fill;
Aki
  • 149
  • 4
  • 13
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);
        }
    }
Jay
  • 17
  • 1
  • 1
    This code is not great. First you don't need the nested loop, which sets the width mode of all the columns to the same thing many () times; you can access the AutoSizeMode and FillWeight properties of each column directly from `GridCol`. Second it is setting the AutoSizeMode for each column to two different values; the second assignment will overwrite the first. – JonP Mar 02 '16 at 15:07
0

To build on AlfredBr's answer, if you hid some of your columns, you can use the following to auto-size all columns and then just have the last visible column fill the empty space:

myDgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
myDgv.Columns.GetLastColumn(DataGridViewElementStates.Visible, DataGridViewElementStates.None).AutoSizeMode = 
    DataGridViewAutoSizeColumnMode.Fill;
RooiWillie
  • 2,198
  • 1
  • 30
  • 36
-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);
}
  • just call that function, it will take care of deciding datagridview height based on number of rows in it – Durga Prasad Guntoju Dec 03 '13 at 13:20
  • 1
    First of all, that does not answer the OP's question. Also (for future reference) include such comment on the answer itself (you can edit it). – Joel Aug 19 '14 at 14:54
-2

Try this :

  DGV.AutoResizeColumns();
  DGV.AutoSizeColumnsMode=DataGridViewAutoSizeColumnsMode.AllCells;
Sachith Wickramaarachchi
  • 5,546
  • 6
  • 39
  • 68
Sudhir
  • 9
  • 1
  • 8