65.9K
CodeProject 正在变化。 阅读更多。
Home

具有可调整大小的多行标题的 DataGrid

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (15投票s)

2005 年 10 月 26 日

3分钟阅读

viewsIcon

192776

downloadIcon

1879

允许用户自定义DataGrid列标题高度,以支持多行标题文本。

Sample Image - SizableColumnHdrDataGrid.jpg

引言

本文向您展示如何设置 DataGrid 标题的高度,并显示多行标题文本。 简单!

使用代码

那么,你想调整 DataGrid 列标题的大小,或者想支持多行列标题文本? 好吧,这是……

  • 添加一个项目引用到 SizableColumnHeaderDataGrid.dll
  • SizableColumnHeaderDataGrid 的实例拖放到你的窗体或控件上。
  • 在属性编辑器(在“Layout(布局)”组下)或代码中设置 ColumnHeaderHeight 属性。
  • 如果你希望你的列标题换行,请确保在列标题文本中的某处使用“\n”。

它看起来和行为就像一个普通的 DataGrid,但仔细观察属性编辑器,你会看到一个名为 ColumnHeaderHeight 的附加属性。以像素为单位设置其值,然后就可以开始了。

你也可以在运行时设置属性,但如果这样做,请务必在 DataGrid 上调用 Invalidate() 以强制重绘。

// Add carriage returns to the column header text
col1.HeaderText = "Row Index\nmulitplied\nby 1";

// Apply new column header size
sizableColumnHeaderDataGrid1.ColumnHeaderHeight = 39;

// Must call invalidate in order to force
// (not necessary if you set the property in the designer)
sizableColumnHeaderDataGrid1.Invalidate();

你现在可以下载 DLL,并快乐地使用你的新玩具,或者继续阅读“他们是怎么做到的?”。

关注点

我尝试了一下 DataGrid,发现如果我更改了字体,标题会自行调整大小。 好的,所以我知道标题能够调整大小,但找不到任何暴露的方式来操作它。 我还发现向标题文本添加回车符是可以接受的,但有一个*轻微的*缺点,你只能看到第一行文本...

然后我使用了 Lutz Roeder 的 Reflector for .NET,在 System.Windows.Forms 命名空间中稍微探索了一下,并找到了 DataGrid.ComputeLayout 方法,该方法使用 headerFontHeight 来设置 ColumnHeaders 矩形的高度,如下面的代码所示

private void ComputeLayout()
{
…
      int num4 = this.headerFontHeight + 6;
      if (this.layout.ColumnHeadersVisible)
      {
            Rectangle rectangle6 = data1.ColumnHeaders;
            rectangle6 = rectangle3;
            rectangle6.Height = num4;
            rectangle3.Y += num4;
            rectangle3.Height -= num4;
            data1.ColumnHeaders = rectangle6;
      }
…
}

哇! 我完成了!

或者我以为是这样。 不幸的是,ComputeLayout 成员和 headerFontHeight 属性都是 private

那么,我怎么让它工作? 输入 System.Reflection

我创建了一个派生的 DataGrid 类并覆盖了 OnPaintOnLayout 事件 – 这两个事件是 System.Windows.Forms.DataGrid 类中调用 ComputeLayout 的地方。(Reflector 提示:如果你在 Reflector 中右键单击一个方法,你可以获得一个调用者图来找出谁在使用选定的成员。)

然后,我在运行时使用反射获取 headerFontHeight 私有属性,并在允许 DataGrid 自身绘制之前重置其值!

这是有趣的反射内容

using System.Windows.Forms;
using System.Diagnostics;
using System.Reflection;

...

private void setColumnHeaderSize()
{
    try
    {

        if (null != this)
        {

            //
            // Use reflection to get the private
            // class property 'headerFontHeight'
            //
            DataGrid myClass = new DataGrid();

            FieldInfo headerFontHeightFieldInfo =
              myClass.GetType().GetField("headerFontHeight",
              BindingFlags.NonPublic|BindingFlags.Instance);

            Int32 currentHeight =
              (Int32)headerFontHeightFieldInfo.GetValue(this);


            //
            // Use public property to redefine 'headerFontHeight'
            //
            if (ColumnHeaderHeight >= 0)
            {
                headerFontHeightFieldInfo.SetValue(this,
                                    ColumnHeaderHeight);
            }

        }

    }

    catch (Exception e)
    {
        System.Diagnostics.Debug.Assert(false, e.ToString());
        throw e;
    }
}

这里是让它工作的稍微不那么令人兴奋的调用

private Int32 columnHeaderHeight = 13;

[Browsable(true),
 Description("Sets the column header height in pixels"),
 Category("Layout"), DefaultValue(13)]
public Int32 ColumnHeaderHeight
{
    get
    {
        return columnHeaderHeight;
    }
    set
    {
        columnHeaderHeight = value;
        OnLayout(null);
    }
}

protected override void OnLayout(LayoutEventArgs levent)
{
    setColumnHeaderSize();
    base.OnLayout (levent);
}

protected override void OnPaint(PaintEventArgs e)
{
    setColumnHeaderSize();
    base.OnPaint (e);
}

买者自负

此代码使用反射来处理 System.Windows.Forms.DataGrid 类的私有成员。 我不能保证如果 Microsoft 更改该类中的代码,它将继续工作。 我只针对 .NET Framework 1.1 进行了测试。

是的,这很酷,但如果它可以……

一些有趣的改进,适用于有更多空闲时间的人

  1. 使标题文本根据列的宽度自动换行。
  2. 使列标题自动更新其高度以适合整个标题文本,考虑到列的宽度。
  3. 使标题可以通过鼠标拖动调整大小(在设计时和运行时)。

历史

  • 版本 1 - 发布于 2005 年 10 月 26 日。
© . All rights reserved.