We had a requirement ones to have multiple header rows. Obvious choice was to use Repeater but we could not define the Columns for the Repeater at the design time. We would know the columns and names only at the design time. AutoGenerateColumns was not available in the repeater. So I had to use GridView.
GridView does not support giving multiple header rows as we do in Repeaters using <tr> tag.
We achieved this by adding new TableRow (html row) at the runtime to the GridView Default table.
In the OnRowCreated event of the GridView,
if (e.Row.RowType == DataControlRowType.Header)
GridViewRow row = new GridViewRow(0, -1, DataControlRowType.Header, DataControlRowState.Normal);
Table t = (Table)gv.Controls;
// Adding Cells
TableCell FileDate = new TableHeaderCell();
FileDate.ColumnSpan = 1;
TableCell cell = new TableHeaderCell();
cell.ColumnSpan = 2; // ********
cell.Text = "Sample Text";
Its also possible to have column spans in the different header rows.