Shows how to merge DataGrid header at run-time.
Download
Introduction
This article describes the technique to merge the header of a DataGrid
by redirecting the Render
method of the DataGrid
items.
Background
I found many times the need to merge the header of a DataGrid
. So, when I was having spare time, I tried to find a way to do it, and here it is. I know that if you need to merge headers, you can use the Repeater
control instead. But if you are fond of DataGrid
(just like me), or may be you already used DataGrid
, then this article is for you.
Using the code
When rendered, a DataGrid
will be converted into a HTML Table
element and the header will be the first HTML TR
element. So, to have a merged header, we need to have control in the rendering of the header. This can be achieved by redirecting the Render
method of the DataGrid
header using the SetRenderMethodDelegate
of the DataGrid
header on ItemCreated
event, like this:
System.Web.UI.WebControls.DataGridItemEventArgs e)
{
//*** Examine if the item created is the header item
ListItemType lit = e.Item.ItemType;
if(ListItemType.Header == lit)
{
//*** Redirect the default header rendering method to our own method
e.Item.SetRenderMethodDelegate(new RenderMethod(NewRenderMethod));
}
}
/// This is our custom render method for the grid header item
/// </summary>
/// <param name="writer"></param>
/// <param name="ctl"></param>
private void NewRenderMethod(HtmlTextWriter writer, Control ctl)
{
//*** We don't need to write the <TR> tag
// because it's already written by the writer
// so now we write the Name column
writer.Write("<TD colspan=\"3\" align=\"center\">Name</TD>\n");
//*** The Age column must have the rowspan attribute
// and must be rendered inside the
// first row so it will centered vertically
TableCell cell = (TableCell)ctl.Controls[ctl.Controls.Count-1];
cell.Attributes.Add("rowspan","2");
cell.RenderControl(writer);
//*** Now we close the first row, so we can insert the second one
writer.Write("</TR>\n");
//*** Add the style attributes that was defined in design time
// to our second row so they both will have the same appearance
DataGrid1.HeaderStyle.AddAttributesToRender(writer);
//*** Insert the second row
writer.RenderBeginTag("TR");
//*** Render all the cells that was defined
// in design time, except the last one
// because we already rendered it above
for(int i=0; i<= ctl.Controls.Count-2; i++)
{
ctl.Controls[i].RenderControl(writer);
}
//*** We don't need to write the </TR> close tag
// because the writer will do that for us
// and so we're done :)
}
DataGrid
(ASPNetDatagridDecorator
class) to have a merge header, and all you need to do is define the header cell like this (you can use the auto format feature, but doesn't work for all):{
// Put user code to initialize the page here
if(!this.IsPostBack)
{
TableCell cell = null;
DataGrid1.DataSource = GetData();
DataGrid1.DataBind();
m_add.DatagridToDecorate = Datagrid2;
ArrayList header = new ArrayList();
// cell = new TableCell();
// cell.Text = "Code";
// cell.RowSpan = 2;
// cell.HorizontalAlign = HorizontalAlign.Center;
// header.Add(cell);
cell = new TableCell();
cell.Text = "Name";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);
cell = new TableCell();
cell.Text = "Name";
cell.ColumnSpan = 3;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);
cell = new TableCell();
cell.Text = "Age";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);
cell = new TableCell();
cell.Text = "School";
cell.ColumnSpan = 3;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);
cell = new TableCell();
cell.Text = "Religion";
cell.RowSpan = 2;
cell.HorizontalAlign = HorizontalAlign.Center;
header.Add(cell);
m_add.AddMergeHeader(header);
Datagrid2.DataSource = GetData();
Datagrid2.DataBind();
}
}