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






4.90/5 (15投票s)
2005 年 10 月 26 日
3分钟阅读

192776

1879
允许用户自定义DataGrid列标题高度,以支持多行标题文本。
引言
本文向您展示如何设置 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
类并覆盖了 OnPaint
和 OnLayout
事件 – 这两个事件是 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 - 发布于 2005 年 10 月 26 日。