Claus
Claus

Reputation: 53

Datagridview Column Auto Size

I have a datagridview with many columns in it, AutoSizeColumnsMode ist set to AllCells. Now my question is, why is there so much empty space next to most of the column headers? For example the empty space for the column header with "HBW 5/250" is nearly the same space as needed for the text. Is there a reason behind it? The problem I have that the whole datagridview should be visible on one screen (24 inch), and I don't know how I can get those columns to only be as large as the longest text is.

It's a C# WinForms application.

I've also looked into all the other options of the AutoSizeColumnsMode Property, but nothing worked for me.

Datagridview

Best regards.

Upvotes: 2

Views: 1574

Answers (2)

Alex Myers
Alex Myers

Reputation: 7155

If your columns are sortable, then there will be extra white space on the right side where the sorting arrow appears. If you don't need your columns to be sortable, then set the column sort mode to NotSortable and you will save a bit of space.

dataGridView1.Columns[0].SortMode = DataGridViewColumnSortMode.NotSortable;

Unfortunately, this will not get rid of all the excess white space in the header. Windowsforms is not great at managing column width when it has to automatically wrap text. If you replace the space in your column header with a new line as seen below, you will notice that all of the white space is gone and it sizes the column perfectly since no wrapping is required.

dataGridView1.Columns[0].HeaderText = "HBW 2,5/62,5";
dataGridView1.Columns[0].HeaderText = "HBW\n2,5/62,5"; //White space gone

Upvotes: 1

Aleksa Ristic
Aleksa Ristic

Reputation: 2499

For more accurate and faster way of auto sizing cells in datagridview i have found somewhere (do not know where) and modified some function so here is how it looks now:

public static void FastAutoSizeColumns(this DataGridView targetGrid)
{
    //If targeted datagridview doesn't have rows just return
    if (targetGrid.Columns.Count < 1)
        return;
    var gridTable = new DataTable();

    // Cast out a DataTable from the target grid datasource.
    // We need to iterate through all the data in the grid and a DataTable supports enumeration.
    gridTable = (DataTable)targetGrid.DataSource;

    targetGrid.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
    // Create a graphics object from the target grid. Used for measuring text size.
    using (var gfx = targetGrid.CreateGraphics())
    {
        // Iterate through the columns.
        for (int i = 0; i < gridTable.Columns.Count; i++)
        {
            // Leverage Linq enumerator to rapidly collect all the rows into a string array, making sure to exclude null values.
            string[] colStringCollection = gridTable.AsEnumerable().Where(r => r.Field<object>(i) != null).Select(r => r.Field<object>(i).ToString()).ToArray();

            // Sort the string array by string lengths.
            colStringCollection = colStringCollection.OrderBy((x) => x.Length).ToArray();

            if (colStringCollection.Length > 0)
            {
                // Get the last and longest string in the array.
                string longestColString = colStringCollection.Last();

                // Use the graphics object to measure the string size.
                var colWidth = gfx.MeasureString(longestColString, targetGrid.Font);

                // If the calculated width is larger than the column header width, set the new column width.
                if (colWidth.Width > targetGrid.Columns[i].HeaderCell.Size.Width)
                {
                    targetGrid.Columns[i].Width = (int)colWidth.Width;
                }
                else // Otherwise, set the column width to the header width.
                {
                    targetGrid.Columns[i].Width = targetGrid.Columns[i].HeaderCell.Size.Width;
                }
            }
            else
            {
                targetGrid.Columns[i].Width = targetGrid.Columns[i].HeaderCell.Size.Width;
            }
        }
    }
}

Import this function somewhere in file (i use separate file for custom extensions) and just call it with:

yourDataGridView.FastAutoSizeCoulmns();

Important note: DataSource need to be type of DataTable (so it cannot be IList or something other so when binding datasource first convert to datatable or modify this function a little)

Upvotes: 1

Related Questions