DataGridView header 稍微向左对齐,即使将其设置为 MiddleCenter

问题描述 投票:0回答:6

我正在为我的 C# 项目中的 DataGridView 设置以下属性 ...

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

但我注意到标题的(即标题单元格中的文本由于某种原因略微向左偏移......虽然数据行完全居中对齐......

什么原因造成的?

c# c#-4.0 datagridview datagridviewcolumn
6个回答
12
投票

因为有一个排序字形(小箭头),DataGridView为此保留了一些空间来显示排序顺序。如果您想禁用排序字形,请将列上的 SortMode 设置为 NotSortable,然后您的文本应该居中。


5
投票

老话题,

我有这个问题,我发现问题是我有网格数据源链接到我的东西,当创建列时,他们默认打开允许排序,这创建了向下箭头按钮进行排序,文本被推到左边。 对此的小修复是:

private void MyDataGridView_ColumnAdded(object sender, DataGridViewColumnEventArgs e)
{
   e.Column.SortMode = DataGridViewColumnSortMode.NotSortable;
}

1
投票

我遇到了和你一样的问题,这似乎是一个框架问题:MS Connect


1
投票

计算出没有反射的字形宽度,并在越界时抑制:

在下面的代码中,我打开和关闭排序,同时将列宽自动调整为列标题文本宽度。排序开/关之间的宽度差异将显示列排序字形使用的宽度。

当列宽设置为小于自动调整宽度时,列会丢失字形,我通过插入对称的左右列填充来抑制它。

我还使用字典存储 ColumnWidth 事件,通过 datagridview 实例在设置宽度时打开和关闭宽度事件。

我称这个疯狂的代码既可以自动调整初始列宽,也可以在用户拖动列宽时管理列标题填充。

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


}

0
投票

您可以在列名称的开头添加两个空格以补偿为字形保留的空间。


0
投票

我知道这个问题已经有 10 多年的历史了,但我想在这里提出我的解决方案,希望其他人可能想要一个快速的代码障碍来使用我的可行解决方案。

问题

DataGridView 上的列标题总是偏离中心,因为“隐藏的”排序字形仅在您单击该列以对列进行排序时(使用默认设置)才显示为右侧的箭头。当尝试将标题文本对齐为

DataGridViewContentAlignment.MiddleCenter
时,由于缺少字形,它看起来并没有真正居中。

解决方法

我使用 DataGridView 中的所有设置手动绘制列标题,除了在未显示时忽略字形大小并在显示时尊重它们(在对列进行排序之后)。

代码

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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.