title: ASP.NET GridView second header row to span main header row
body: <p>I have an ASP.NET GridView which has columns that look like this:</p>
  
  <pre><code>| Foo | Bar | Total1 | Total2 | Total3 |
  </code></pre>
  
  <p>Is it possible to create a header on two rows that looks like this?</p>
  
  <pre><code>|           |  Totals   |    
  | Foo | Bar | 1 | 2 | 3 |
  </code></pre>
  
  <p>The data in each row will remain unchanged as this is just to pretty up the header and decrease the horizontal space that the grid takes up.  </p>
  
  <p>The entire GridView is sortable in case that matters.  I don't intend for the added "Totals" spanning column to have any sort functionality.</p>
  
  <p><strong>Edit:</strong></p>
  
  <p>Based on one of the articles given below, I created a class which inherits from GridView and adds the second header row in.</p>
  
  <pre><code>namespace CustomControls
  {
      public class TwoHeadedGridView : GridView
      {
          protected Table InnerTable
          {
              get
              {
                  if (this.HasControls())
                  {
                      return (Table)this.Controls[0];
                  }
  
                  return null;
              }
          }
  
          protected override void OnDataBound(EventArgs e)
          {
              base.OnDataBound(e);
              this.CreateSecondHeader();
          }
  
          private void CreateSecondHeader()
          {
              GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
  
              TableCell left = new TableHeaderCell();
              left.ColumnSpan = 3;
              row.Cells.Add(left);
  
              TableCell totals = new TableHeaderCell();
              totals.ColumnSpan = this.Columns.Count - 3;
              totals.Text = "Totals";
              row.Cells.Add(totals);
  
              this.InnerTable.Rows.AddAt(0, row);
          }
      }
  }
  </code></pre>
  
  <p>In case you are new to ASP.NET like I am, I should also point out that you need to:</p>
  
  <p>1) Register your class by adding a line like this to your web form:</p>
  
  <pre><code>&lt;%@ Register TagPrefix="foo" NameSpace="CustomControls" Assembly="__code"%&gt;
  </code></pre>
  
  <p>2) Change asp:GridView in your previous markup to foo:TwoHeadedGridView.  Don't forget the closing tag.</p>
  
  <p><strong>Another edit:</strong></p>
  
  <p>You can also do this without creating a custom class.</p>
  
  <p>Simply add an event handler for the DataBound event of your grid like this:</p>
  
  <pre><code>protected void gvOrganisms_DataBound(object sender, EventArgs e)
  {
      GridView grid = sender as GridView;
  
      if (grid != null)
      {
          GridViewRow row = new GridViewRow(0, -1,
              DataControlRowType.Header, DataControlRowState.Normal);
  
          TableCell left = new TableHeaderCell();
          left.ColumnSpan = 3;
          row.Cells.Add(left);
  
          TableCell totals = new TableHeaderCell();
          totals.ColumnSpan = grid.Columns.Count - 3;
          totals.Text = "Totals";
          row.Cells.Add(totals);
  
          Table t = grid.Controls[0] as Table;
          if (t != null)
          {
              t.Rows.AddAt(0, row);
          }
      }
  }
  </code></pre>
  
  <p>The advantage of the custom control is that you can see the extra header row on the design view of your web form.  The event handler method is a bit simpler, though.</p>