DataGridView header alignment slightly to left even after setting it to MiddleCenter
Asked Answered
C

6

6

I'm setting the following properties for a DataGridView in my C# project ...

sampleDataGridView.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
sampleDataGridView.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;

But I notice that the heading's (i.e. text in header cell is offset slightly to the left, for some reason .. The data rows alignment in perfectly in center though ...

What can be causing this ?

Cellule answered 5/3, 2012 at 9:3 Comment(0)
O
13

It is because there is a sorting glyph (little arrow) for which the DataGridView reserves some space to show the sort order. If you want to disable the sorting glyph, set the SortMode on your column to NotSortable, and your text should then be centered.

Overexcite answered 22/9, 2014 at 17:57 Comment(0)
L
5

Old topic,

i had this problem, and i found out that the problem was that i had the grid datasource-linked to my stuff, and when the columns where created they put the ALLOW SORT ON by default, which created the arrow down button to sort, and the text gets pushed to the left. small fix to this is:

private void MyDataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
   e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
}
Leonard answered 5/3, 2019 at 20:8 Comment(0)
G
2

I know this question is over 10 years old but I wanted to toss my solution on here in hopes someone else might want a quick code snag to use my workable solution.

Issue

The column headers on a DataGridView are always off center due to the "hidden" sorting glyphs that shop up as arrows to the right only when you click the column to sort the column (using default settings). When trying to align the header text as DataGridViewContentAlignment.MiddleCenter it looks like it's not really centered due to the missing glyphs.

Workaround

I manually paint the column headers using all the settings in the DataGridView with the exception of ignoring the glyphs size when they are not shown and respecting them when they are shown (after you sort the column).

Code

private void DataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
    DataGridView dgv = sender as DataGridView;
    SortOrder sort = dgv.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection;

    if (e.RowIndex == -1 && sort == SortOrder.None)
    {
        string headerText = dgv.Columns[e.ColumnIndex].HeaderText;
        Font headerFont = e.CellStyle.Font;
        Brush headerBrush = new SolidBrush(e.CellStyle.ForeColor);
        DataGridViewContentAlignment headerAlignment = e.CellStyle.Alignment;

        e.Paint(e.ClipBounds, (DataGridViewPaintParts.All & ~DataGridViewPaintParts.ContentForeground));

        SizeF stringSize = TextRenderer.MeasureText(e.Graphics, headerText, e.CellStyle.Font, e.CellBounds.Size);
        Rectangle p = e.CellBounds;
        switch (headerAlignment)
        {
            case DataGridViewContentAlignment.TopCenter:
                p.Offset(
                    e.CellBounds.Width / 2 - (int)(stringSize.Width / 2),
                    0
                );
                break;
            case DataGridViewContentAlignment.TopRight:
                p.Offset(
                    e.CellBounds.Width - (int)stringSize.Width,
                    0
                );
                break;
            case DataGridViewContentAlignment.MiddleLeft:
                p.Offset(
                    0,
                    e.CellBounds.Height / 2 - (int)(stringSize.Height / 2)
                );
                break;
            case DataGridViewContentAlignment.MiddleCenter:
                p.Offset(
                    e.CellBounds.Width / 2 - (int)(stringSize.Width / 2),
                    e.CellBounds.Height / 2 - (int)(stringSize.Height / 2)
                );
                break;
            case DataGridViewContentAlignment.MiddleRight:
                p.Offset(
                    e.CellBounds.Width - (int)stringSize.Width,
                    e.CellBounds.Height / 2 - (int)(stringSize.Height / 2)
                );
                break;
            case DataGridViewContentAlignment.BottomLeft:
                p.Offset(
                    0,
                    e.CellBounds.Height - (int)stringSize.Height
                );
                break;
            case DataGridViewContentAlignment.BottomCenter:
                p.Offset(
                    e.CellBounds.Width / 2 - (int)(stringSize.Width / 2),
                    e.CellBounds.Height - (int)stringSize.Height
                );
                break;
            case DataGridViewContentAlignment.BottomRight:
                p.Offset(
                    e.CellBounds.Width - (int)stringSize.Width,
                    e.CellBounds.Height - (int)stringSize.Height
                );
                break;
            default:
                p.Offset(
                    0,
                    0
                );
                break;
        }

        e.Graphics.DrawString(headerText, headerFont, headerBrush, new PointF(p.X, p.Y));
        e.Handled = true;
    }
}
Garnishment answered 17/4, 2023 at 19:37 Comment(0)
R
1

I had the same problem as you and it seems it's a framework issue: MS Connect

Rakia answered 5/3, 2012 at 10:3 Comment(0)
C
1

Figure out the glyph width without refection and supress when out of line:

In the following code I turn on and off sorting while autoadjusting column width to the column header text width. The difference in width between sorting on/off will reveal the width used by the column sort glyph.

As column looses the glyph when column width is set less than autoadjusted width I supress it by inserting symetric left and right column padings.

I also use a dictionary to store ColumnWidth events by datagridview instance to turn width events on and off while seting the width.

I call this crazy code both to autoadjust initial column widths and to manage the column header padings when user drags column widths.

void AdaptColumnHeaderText(DataGridViewColumn column, bool autoSize=false)
{

    //Supress column width events
    if (dataGridViewColumnWidthEventHandlers.ContainsKey(column.DataGridView))
    {
        dataGridView1.ColumnWidthChanged -= dataGridViewColumnWidthEventHandlers[column.DataGridView];
    }

    //Save initial column with as preferred
    var w_preferred = column.Width;

    if (
            column.SortMode.Equals(DataGridViewColumnSortMode.Automatic) &&
            column.HeaderCell.Style.Alignment.Equals(DataGridViewContentAlignment.MiddleCenter))
    {
        //remove all header padding
        column.HeaderCell.Style.Padding = new Padding(0, 0, 0, 0);

        //Fit column width to header text with AND sort glyph
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.ColumnHeader;

        //save column width sort enabled
        var w_sort = column.Width;

        //Fit column width to header text with NO sort glyph
        column.SortMode = DataGridViewColumnSortMode.NotSortable;

        //save column width when sort disable
        var w_nosort = column.Width;

        //Calculate width consumed by sort glyph
        var w_glyph = w_sort - w_nosort;

        //Nominal column width if glyph width applied left and right of header text
        var w_nominal = w_glyph + w_nosort + w_glyph;

        //Disable column width autosize
        column.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;

        //Enable column autosorting
        column.SortMode = DataGridViewColumnSortMode.Automatic;

        //If autosize option - ignore preferred width and set to nominal
        if (autoSize)
        {
            w_preferred = w_nominal;       
        }

        //Pad depending on final column width
        if (w_preferred >= w_nominal)
        {
            //Preferred width greater than nominal - pad left of text to balance width used by glyph
            column.HeaderCell.Style.Padding = new Padding(w_glyph, 0, 0, 0);
        }
        else
        {
            //Two symetric glyphs will not fit - pad left and right to supress glyph  
            w_glyph = (w_preferred - w_nosort) / 2;
            column.HeaderCell.Style.Padding = new Padding(w_glyph, 0, w_glyph, 0);
        }
        column.Width = w_preferred;

        Console.WriteLine("name:{0}, glyph:{1}, w_preferred:{2}", column.Name, w_glyph, w_preferred);
    }

    //re-enable column width events
    if (dataGridViewColumnWidthEventHandlers.ContainsKey(column.DataGridView))
    {
        dataGridView1.ColumnWidthChanged += dataGridViewColumnWidthEventHandlers[column.DataGridView];
    }


}
Carl answered 18/9, 2017 at 13:17 Comment(0)
M
0

You can add two spaces at the beginning of the column name to compensate the space reseved for the glyph.

Mange answered 17/5, 2020 at 11:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.