ReoGrid supports multi-row column headers, allowing you to create complex header structures with multiple rows, merged cells, and individual styling. This feature is useful for displaying hierarchical or grouped column headers.

Multiple Cell Header

Creating Multi-Row Headers

Access the extension column header via the ExtensionColumnHeader property:

var extensionHeader = worksheet.ExtensionColumnHeader;

Set the Number of Header Rows

Use the RowCount property or SetRowCount method to define the number of header rows (1 to 10):

// Set 3 header rows
extensionHeader.SetRowCount(3);

// Or use the property
extensionHeader.RowCount = 3;

The result: Multiple Cell Header

Note: The extension column header supports between 1 and 10 rows. Setting RowCount to 1 effectively restores the default single-row header.

Get Header Row Count and Total Height

int rowCount = extensionHeader.RowCount;
int totalHeight = extensionHeader.TotalHeight; // Total height in pixels of all header rows

Accessing Header Cells

Cells in multi-row headers use (row, column) coordinates with the origin (0, 0) at the top-left corner:

Multiple Cell Header

// Access a cell by row and column index
HeaderCell cell = extensionHeader[0, 0];

// Or via the Cells collection
HeaderCell cell2 = extensionHeader.Cells[1, 3];

HeaderCell Properties

PropertyTypeDescription
TextstringDisplay text of the header cell
StyleHeaderCellStyleStyle object for customizing appearance
BodyIHeaderBodyCustom header body for rendering
RowIndexintRow index of the cell (read-only)
ColumnIndexintColumn index of the cell (read-only)
IsValidboolWhether the cell is valid (not consumed by a merge)
IsMergedboolWhether the cell is part of a merged range
IsMergedStartCellboolWhether this is the top-left cell of a merged range
MergedStartCellHeaderCellThe top-left cell of the merge (returns self if not merged)
CellPositionCellPositionPosition as a CellPosition struct
RangePositionRangePositionRange if this cell is part of a merge
PositionAddressstringAddress string (e.g., โ€œA1โ€ or โ€œA1:B2โ€ if merged)
TextColorSolidColor?Text color (deprecated โ€” use Style.TextColor)
BackColorSolidColor?Background color (deprecated โ€” use Style.BackColor)

Merging and Unmerging Cells

Merge Cells

Use MergeCells to combine cells. Parameters are: start row, start column, row span, column span.

extensionHeader.MergeCells(int startRow, int startColumn, int rowSpan, int columnSpan);

Example:

// Merge cell (0,0) spanning 3 rows and 1 column
extensionHeader.MergeCells(0, 0, 3, 1);

// Merge from cell (0,1) spanning 1 row and 4 columns
extensionHeader.MergeCells(0, 1, 1, 4);

Multiple Cell Header

Set Cell Text

extensionHeader[0, 0].Text = "No.";
extensionHeader[0, 1].Text = "Category A";

Multiple Cell Header

Complete Multi-Row Header Example

Here is a complete example creating a complex hierarchical header:

// Set 3 rows
extensionHeader.SetRowCount(3);

// Merge cells to create the hierarchy
extensionHeader.MergeCells(0, 0, 3, 1);     // "No." spans all 3 rows

extensionHeader.MergeCells(0, 1, 1, 4);     // Top-level group 1
extensionHeader.MergeCells(1, 1, 1, 2);     // Mid-level group 1a
extensionHeader.MergeCells(1, 3, 1, 2);     // Mid-level group 1b

extensionHeader.MergeCells(0, 5, 3, 1);     // "Target" spans all 3 rows

extensionHeader.MergeCells(0, 6, 1, 4);     // Top-level group 2
extensionHeader.MergeCells(1, 6, 2, 1);     // Mid-level group 2a (spans 2 rows)
extensionHeader.MergeCells(1, 8, 2, 2);     // Mid-level group 2b (spans 2 rows)

// Set text for all cells
extensionHeader[0, 0].Text = "No.";
extensionHeader[0, 1].Text = "Category A";
extensionHeader[1, 1].Text = "Sub-A1";
extensionHeader[1, 3].Text = "Sub-A2";
extensionHeader[2, 1].Text = "Detail 1";
extensionHeader[2, 2].Text = "Detail 2";
extensionHeader[2, 3].Text = "Detail 3";
extensionHeader[2, 4].Text = "Detail 4";
extensionHeader[0, 5].Text = "Target";
extensionHeader[0, 6].Text = "Category B";

Result: Multiple Cell Header

Unmerge Cells

extensionHeader.UnmergeCells(0, 7);

Check Merge Status

var cell = extensionHeader[0, 0];

if (cell.IsMerged)
{
    Console.WriteLine($"Cell is merged. Start cell: {cell.MergedStartCell.PositionAddress}");
}

if (cell.IsMergedStartCell)
{
    Console.WriteLine($"This is the start of a merge spanning {cell.RangePosition}");
}

// Check if a cell contains another
bool contains = cell.Contains(extensionHeader[1, 0]);

Header Cell Styling

Each header cell has a Style property of type HeaderCellStyle for customizing its appearance.

HeaderCellStyle Properties

PropertyTypeDefaultDescription
TextColorSolidColor?null (system default)Text color. Set to null to remove.
BackColorSolidColor?null (system default)Background color. Set to null to remove.
FontSizefloat10.5f (WinForms)Font size
FontFamilystringโ€Arialโ€ (WinForms)Font family name (WinForms)
FontFontFamilySystem default (WPF)Font family (WPF)
FontStyleFontStylesRegularFont style (bold, italic)
FontWeightFontWeightSystem default (WPF)Font weight (WPF only)
TextUnderLineboolfalseWhether text is underlined
HorizontalAlignmentReoGridHorAlignCenterHorizontal text alignment
VerticalAlignmentReoGridVerAlignMiddleVertical text alignment
TextWrapModeTextWrapModeNoWrapText wrapping mode
PaddingPaddingValue(empty)Cell padding

Example: Style Header Cells

// Set background color for a category header
extensionHeader[0, 1].Style.BackColor = new SolidColor(Color.LightBlue);

// Set font style for a title cell
extensionHeader[0, 0].Style.FontSize = 12;
extensionHeader[0, 0].Style.FontStyle = FontStyles.Bold;
extensionHeader[0, 0].Style.TextColor = new SolidColor(Color.DarkBlue);

// Set text alignment
extensionHeader[0, 0].Style.HorizontalAlignment = ReoGridHorAlign.Center;
extensionHeader[0, 0].Style.VerticalAlignment = ReoGridVerAlign.Middle;

// Enable text wrapping for long header text
extensionHeader[0, 1].Style.TextWrapMode = TextWrapMode.WordBreak;

// Add padding
extensionHeader[0, 0].Style.Padding = new PaddingValue(4, 2, 4, 2);

Reset a Cell Style

extensionHeader[0, 0].Style.Reset();

Copy Style Between Cells

extensionHeader[1, 1].Style.CopyFrom(extensionHeader[0, 1].Style);

Convert to WorksheetRangeStyle

Convert a HeaderCellStyle to a WorksheetRangeStyle for use with worksheet cells:

WorksheetRangeStyle rangeStyle = extensionHeader[0, 0].Style.ToRangeStyle();

Adjusting Row Height

Each header rowโ€™s height can be adjusted individually:

// Set height of the first header row
extensionHeader.Rows[0].Height = 40;

// Set height of the second header row
extensionHeader.Rows[1].Height = 25;

// Access row count
int count = extensionHeader.Rows.Count;

Mouse Events

The extension column header provides mouse events for interactive behavior:

// Mouse events on the entire extension header
extensionHeader.MouseDown += (s, e) =>
{
    Console.WriteLine($"Mouse down at row:{e.RowIndex}, col:{e.ColumnIndex}");
};

extensionHeader.MouseMove += (s, e) =>
{
    Console.WriteLine($"Mouse move at row:{e.RowIndex}, col:{e.ColumnIndex}");
};

extensionHeader.MouseUp += (s, e) =>
{
    Console.WriteLine($"Mouse up at row:{e.RowIndex}, col:{e.ColumnIndex}");
};

Header Mouse Event Args

PropertyTypeDescription
RowIndexintRow index in the extension header (ignores merged cells)
ColumnIndexintColumn index in the extension header (ignores merged cells)
PositionToColumnintMouse position relative to the physical column

Individual Cell Mouse Events

Each HeaderCell also fires its own mouse events:

var cell = extensionHeader[0, 0];

cell.MouseDown += (s, e) =>
{
    Console.WriteLine($"Clicked header cell: {e.HeaderCell.Text}");
};

cell.MouseUp += (s, e) =>
{
    // Handle mouse up
};

cell.MouseMove += (s, e) =>
{
    // Handle mouse move
};

HeaderCellMouseEventArgs

PropertyTypeDescription
HeaderCellHeaderCellThe header cell that triggered the event
IsCancelledboolSet to true to cancel the event

Column Selection

Multi-row column headers always allow individual columns to be selected, regardless of whether cells are merged horizontally. Selected columns are displayed in a highlighted color:

Multiple Cell Header

If only some columns of a merged cell area are selected, those cells are partially highlighted:

Multiple Cell Header

Hiding Columns

When a column is hidden, a thick line appears in place of the hidden column within the multi-row header:

Multiple Cell Header for multiple lines

Use with Freeze Panes

Multi-row column headers work with worksheet freeze just like regular column headers. When the worksheet is scrolled, frozen columns remain visible:

Multiple Cell Header

Use with Outlines

Multi-row column headers work with outlines. If columns are collapsed, the corresponding header cells are hidden:

Multiple Cell Header

Reset Extension Header

Reset the extension header to its default state (removes all merges and text):

extensionHeader.Reset();

Convert to PartialGrid

Export the extension header as a PartialGrid object:

// Export all columns
var partialGrid = extensionHeader.ConvertToPartialGrid();

// Export only specific columns
var partialGrid = extensionHeader.ConvertToPartialGrid(new int[] { 0, 1, 2, 3 });
Was this article helpful?