This article shows you how to set the height of your
DataGrid headers and show multi-line header text. Easily!
Using the code
So, you want to adjust the size of your
DataGrid column headers, or want to support multi-line column header text? Well, here you go…
- Add a project reference to SizableColumnHeaderDataGrid.dll.
- Drop an instance of the
SizableColumnHeaderDataGrid onto your form or control.
- Set the
ColumnHeaderHeight property in the property editor (under the Layout group) or in code.
- If you want your column headers to wrap, be sure to use “\n” somewhere in the column header text.
It will look and act just like a regular
DataGrid, but look closely in the properties editor, and you will see an additional property named
ColumnHeaderHeight. Set its value in pixels, and away you go.
You can also set the property at runtime, but if you do, be sure to then call
Invalidate() on your
DataGrid to force a repaint.
col1.HeaderText = "Row Index\nmulitplied\nby 1";
sizableColumnHeaderDataGrid1.ColumnHeaderHeight = 39;
You can download the DLL now and live happily ever after with your new toy, or continue reading for the How did they do that? stuff.
Points of Interest
I fooled around with the
DataGrid and found that, if I changed the font, the header would resize itself. Okay, so I know the header is capable of resizing but cannot find any exposed way to manipulate it. I also found that adding carriage returns to my header text was acceptable, with the *slight* drawback that you can only see the first line of text...
I then used Lutz Roeder’s Reflector for .NET to poke around a bit in the
System.Windows.Forms namespace, and found my way to the
DataGrid.ComputeLayout method which uses the
headerFontHeight to set the height of the
ColumnHeaders rectangle as shown in the following code:
private void ComputeLayout()
int num4 = this.headerFontHeight + 6;
Rectangle rectangle6 = data1.ColumnHeaders;
rectangle6 = rectangle3;
rectangle6.Height = num4;
rectangle3.Y += num4;
rectangle3.Height -= num4;
data1.ColumnHeaders = rectangle6;
Woohoo, I’m done!
Or so I thought. Unfortunately, both the
ComputeLayout member and the
headerFontHeight property are
So, how did I make it work? Enter
I created a derived
DataGrid class and overrode the
OnLayout events – these are the two places that call
ComputeLayout in the
System.Windows.Forms.DataGrid class. (Reflector tip: if you right click on a method in Reflector, you can get a Callee Graph to find out who is using the selected member.)
I then used reflection at runtime to get the
headerFontHeight private property, and reset its value before allowing the
DataGrid to paint itself!
Here's the fun reflection stuff:
private void setColumnHeaderSize()
if (null != this)
DataGrid myClass = new DataGrid();
FieldInfo headerFontHeightFieldInfo =
Int32 currentHeight =
if (ColumnHeaderHeight >= 0)
catch (Exception e)
And here are the slightly less exciting calls to make it work:
private Int32 columnHeaderHeight = 13;
Description("Sets the column header height in pixels"),
public Int32 ColumnHeaderHeight
columnHeaderHeight = value;
protected override void OnLayout(LayoutEventArgs levent)
protected override void OnPaint(PaintEventArgs e)
This code works using reflection to monkey with private members of the
System.Windows.Forms.DataGrid class. I cannot guarantee that it will continue to work if Microsoft changes code in that class. I have tested this only against the .NET Framework 1.1.
Yeah that's cool, but what if it could…
Some fun improvements available for someone with more free time:
- Make the header text auto-wrap based on the width of the column.
- Make the column headers auto update their height to fit the entire header text, given the width of the column.
- Make the headers sizable with mouse drags (in design-time and run-time).
- Version 1 - released 10/26/2005.