I am populating a DataGridView control on a Windows Form (C# 2.0 not WPF).
My goal is to display a grid that neatly fills all available width with cells - i.e. no un
Slightly neater C# code from Miroslav Zadravec's code assuming all columns are to be autosized
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;
}
DataGridView.Columns, change AutoSizeMode to a valid one, collect width value and set it back after change AutoSizeMode to DataGridViewAutoSizeColumnMode.None). Form.Show() or Form.ShowDialog(). So I put this code snippet in the Form.Shown event and this works for me. My transformed code, reguardless of whatever DataGridView.AutoSizeColumnsMode set before, I use DataGridViewColumn.GetPreferredWidth() instead of changing DataGridViewColumn.AutoSizeMode and set the width value immediately, then change DataGridView.AutoSizeColumnsMode once:
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;
}
Be sure to set
dataGridView.AllowUserToResizeColumns = true;
I don't know how come this only works after the form is shown.
foreach (DataGridViewColumn c in dataGridView.Columns)
c.Width = c.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);
This should work whether the dataGridView has been displayed or not (i.e. even if called from the class constructor).
The same method, but with DataGridViewAutoSizeColumnMode.DisplayedCells, fails in the above case for the obvious reason - no cell has been displayed yet! For some non-obvious reason, AutoResizeColumns also fails in this case.
I had to do this in VB and prefer to split it out to a method that I placed in a Module. You can add the Fill column as another ByRef parameter if desired.
''' <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
This autofits all columns according to their content, fills the remaining empty space by stretching a specified column and prevents the 'jumping' behaviour by setting the last column to fill for any future resizing.
// 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;
If you bind your datasource to a datatable for example, you need to set the properties after the binding is done:
private void dgv_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
{
dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dgv.AutoResizeColumns();
dgv.AllowUserToResizeColumns = true;
}