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