Extending ASP.NET Datagrid control
Abstract
ASP.NET is built on extensible architecture. Each and every control provides a set of basic functionalities which that control supports. If we want to extend/change the existing functionality for any control, .net framework provides ways to do that.
So for example, if we want to extend Datagrid control we just have to create a class which will inherit from System.Web.UI.WebControls.DataGrid class. By doing this, all the public and protected members of DataGrid class will be available to our class and now we can customize the existing Datagrid in the way we want.
To demonstrate it, we will create a MyCustomDataGrid custom control class which will inherit from System.Web.UI.WebControls.DataGridclass. In this custom control class we will change the default behavior of AlternatingItemStyle element present inside DataGrid. The default implementation of AlternatingItemStyle is that it can be used to change the common style attribute like forecolor, backcolor, font etc. for alternating items inside Datagrid. Now we will change this default behavior for color attribute to alternate the row’s style for every N rows instead of a single row.
Let’s take a look at properly commented source code that how we can achieve the above functionality.
[
DefaultProperty("Text"),
ToolboxData("<{0}:CustomDatagrid runat=server></{0}:CustomDatagrid>")
]
public class CustomDatagrid : System.Web.UI.WebControls.DataGrid
{
private string text;
[Bindable(true),Category("Appearance"),DefaultValue("")]
public string Text
{
get { return text; }
set { text = value;}
}
private Int16 _rows;
public Int16 AlternatingRows
{
get { return _rows; }
set { _rows = value; }
}
/*
This method that will write the HTML necessary to start TABLE
(including the ID, the style tag, etc..). We'll use the AddAttribute method to render our control's "id" property. We will get all the style information. As long as our control has a ControlStyle object we can simply call ControlStyle.AddAttributesToRender method.
NOTE :- If we override Render method we need to take care of RenderContent method as well.
*/
protected override void Render(HtmlTextWriter output)
{
// Create the ID attribute of our TABLE
output.AddAttribute("id", this.ID);
// Create the style attribute
if (this.ControlStyleCreated && this.ControlStyle != null)
{
ControlStyle.AddAttributesToRender(output);
}
// Support style sheets
if (this.CssClass != string.Empty)
output.AddAttribute("class", CssClass);
// Render <table> tag
output.RenderBeginTag("table");
// Render all of the rows
this.RenderContents(output);
output.RenderEndTag();
}
/*
This method builds all the HTML neccessary to represent DataGrid
Rows/Items. They can be Header, Footer, Item, Alternating Item etc.
1. We need to know that how many rows has to be rendered with the current style and what all styles are applied on those rows.
2. There is a DataGridTable object inside Datagrid control which holds all the rows to be rendered. So we will loop on this object to find the rows.
*/
protected override void RenderContents(HtmlTextWriter output)
{
// The number of rows that have had our style applied.
Int16 rows = 0;
// The style of DataGridItem
TableItemStyle _style = this.ItemStyle;
// Check if Data grid is empty or not.
if (HasControls())
{
foreach (DataGridItem r in Controls[0].Controls)
{
if (r.ItemType == ListItemType.Item ||
r.ItemType == ListItemType.AlternatingItem)
{
rows += 1;
// Have we rendered enough rows at the current style?
if (rows > _rows) {
// Switch from the style we were using to the alternate style
if (_style == this.AlternatingItemStyle)
{
_style = this.ItemStyle;
}
else
{
_style = this.AlternatingItemStyle; }
//Reset row counter
rows = 1;
}
//Write the modified style as an HTML.
_style.AddAttributesToRender(output);
}
Let other Items to render without any change.
else
{
switch (r.ItemType)
{
case ListItemType.Header:
this.HeaderStyle.AddAttributesToRender(output);
break;
case ListItemType.Footer:
this.FooterStyle.AddAttributesToRender(output);
break;
case ListItemType.Pager:
this.PagerStyle.AddAttributesToRender(output);
break;
case ListItemType.EditItem:
this.EditItemStyle.AddAttributesToRender(output);
break;
case ListItemType.SelectedItem:
this.SelectedItemStyle.AddAttributesToRender(output);
break;
}
}
// Render DataGridItem (HTML row)
output.RenderBeginTag("tr");
// Render the cells for this DataGridItem
for (int w = 0; w < r.Controls.Count; w++)
{
r.Controls[w].RenderControl(output);
}
output.RenderEndTag();
}
}
}
}
Once we are done writing the control we can use it on web form page as: -
<cc1:CustomDatagrid id="CustomDatagrid1"
runat="server" AlternatingRows="3" >
<AlternatingItemStyle BackColor="#cccc99" />
<EditItemStyle BackColor="#ccccff" />
<ItemStyle BackColor="#336699" />
<SelectedItemStyle BackColor="#cc9966" />
</cc1:CustomDatagrid>
Now run the aspx page and see the output.