Adding a Second Header to an ASP.NET Gridview

Last week, I had some specs to create a grid view in ASP that had normal column headers, as one might expect, and then also “super” column headers, where the columns were categorized. So, if, for instance, you had columns for “Dog”, “Cat”, and “Bird”, those three headers might have a “super-header” called “Pet”, in what basically amounts to a two-tiered categorization hierarchy.

Visually, what I wanted to do was create a second header row on top of the one populated from my data source, but there didn’t seem to be any good way to make this happen through the properties of the GridView. It also seemed like a mess to try to do this through CSS and somehow matching client side HTML styling with a service-side generated table. So, to combat this, I got ahold of the grid view’s table and manually added a row to it:

protected void GridView_DataBound(object sender, EventArgs e)
{
    var myGridView = (GridView)sender;
    if (myGridView.Controls.Count > 0)
        AddSuperHeader(myGridView);
}

private static void AddSuperHeader(GridView gridView)
{
    var myTable = (Table)gridView.Controls[0];
    var myNewRow = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
    myNewRow.Cells.Add(MakeCell());
    myNewRow.Cells.Add(MakeCell("PETS", 3));
    myNewRow.Cells.Add(MakeCell("ZOO ANIMALS", 3));
    myNewRow.Cells.Add(MakeCell("VARMINTS", 3));
    myNewRow.Cells.Add(MakeCell("GAME ANIMALS", 3));
    myTable.Rows.AddAt(0, myNewRow);
}

private static TableHeaderCell MakeCell(string text = null, int span = 1)
{
    return new TableHeaderCell() { ColumnSpan = span, Text = text ?? string.Empty, CssClass = "table-header" };
}

What’s going on here is that when the grid is data bound, I check to see if data exists and, if so, I add my “super header”. This consists of grabbing the grid view’s first control, which is a table. This is kind of hackalicious in that a change to the ordering of the grid view’s controls collection is a breaking change, but c’est la vie. Once we’ve got ahold of that table, it becomes relatively straightforward to create a row for it using code and to assign it a class to allow further styling in CSS.

So, quick tip for today, and my first ASP.NET oriented one, as I learn the ins and outs of webforms and hopefully later ASP.NET MVC.

Cheers!