Search code examples
c#winformsdatagridviewautosizedatagridviewcomboboxcell

Autosize a DataGridViewComboBoxCell which uses custom painting


My DataGridView has a DataGridViewComboBoxColumn on it. This is my custom cell painting handler:

private void dataGridView_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    if (e.ColumnIndex == 1 && e.RowIndex >= 0)
    {
        e.PaintBackground(e.CellBounds, true);
        //e.PaintContent(e.CellBounds);

        Graphics g = e.Graphics;
        Color c = Color.Empty;
        string s = "";
        Brush br = SystemBrushes.WindowText;
        Brush brBack;
        Rectangle rDraw;

        rDraw = e.CellBounds;
        rDraw = Rectangle.FromLTRB(e.CellBounds.Left, e.CellBounds.Top, e.CellBounds.Right, e.CellBounds.Bottom - 1);

        brBack = Brushes.White;
        Pen penGridlines = new Pen(dataGridView.GridColor);
        g.DrawRectangle(penGridlines, rDraw);
        g.FillRectangle(brBack, rDraw);
        penGridlines.Dispose();

        if (dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
        {
            ComboboxColourItem oColourItem = (ComboboxColourItem)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value;
            s = oColourItem.ToString();
            c = oColourItem.Value;
        }

        int butSize = e.CellBounds.Height;
        Rectangle rbut = new Rectangle(e.CellBounds.Right - butSize,
                                       e.CellBounds.Top, butSize, butSize);
        ComboBoxRenderer.DrawDropDownButton(e.Graphics, rbut,
                   System.Windows.Forms.VisualStyles.ComboBoxState.Normal);


        if (c != Color.Empty)
        {
            SolidBrush b = new SolidBrush(c);
            Rectangle r = new Rectangle(e.CellBounds.Left + 6,
                                         e.CellBounds.Top + 5, 10, 10);
            g.FillRectangle(b, r);
            g.DrawRectangle(Pens.Black, r);
            g.DrawString(s, Form.DefaultFont, Brushes.Black,
                         e.CellBounds.Left + 25, e.CellBounds.Top + 3);

            b.Dispose();
        }

        e.Handled = true;
    }
}

When I go to autosize my populated column by double-clicking the right edit of the DVG this is what happens:

Autosize

How do I adjust the behaviour so that when autosizes it takes into account the combo dropdown?

Thanks.


Solution

  • When you double click on a column header divider to make the column auto size, it makes the column width equals to widest cell. Width of a combo box cell in auto size mode is calculated using:

    • Width of formatted value
    • width of combo box button
    • cell style padding
    • error icon width
    • some extra padding around text and button and icon

    Quick Fix

    In your case those colored rectangles occupy space but their width and spaces around them will not be calculated when calculating auto size of cell.

    As a simple solution you can add some padding to the column. You can do it in designer, by editing columns and set the padding in DefaultCellStyle for the column. Also using code you can write for example:

    column.DefaultCellStyle.Padding = new Padding(16,0,16,0);
    

    Long term solution

    If the column is a reusable column type, I recommend you to create your custom column type. Then you can encapsulate painting logic and calculating size and some other features in your custom cell. If you decide to create your custom cell, you will find these methods related to the problem useful: