Working with Dynamic Templates in ASP.NET

Introduction
Some controls in ASP.NET like the Repeater control require templates to display data. These templates can be applied either statically or dynamically.
Static templates require editing the source code of the ASP.NET control. For example:

On the other hand, dynamic templates are applied at runtime and do not require modifying the source code of the Repeater control.
There are advantages and disadvantages of both approaches. Static templates are faster since they do not incur overhead at runtime but are less flexible, whereas dynamic templates are initially slow but provide more flexibility to the developer.
Background
A Repeater control is a DataBound
control in ASP.NET which can be used to display data from a back end database table. But it does not have its own default layout. In order to provide layout to the Repeater control, templates must be defined for it.
The most common way of creating templates for a Repeater control is to modify the source code of the Repeater. However templates can also be created programmatically as is demonstrated by this article.
Using the Code
To create dynamic templates, you must create a class that implements the ITemplate
interface as follows:
public class MyTemplate : ITemplate
{
ListItemType type; // The type of template (Header, Footer, Item, AlternatingItem
LiteralControl lc; // To hold the template code
DataSet ds; // To hold the data to be bound
static int ctr; // To track current row.
public MyTemplate(ListItemType type, DataSet ds)
{
this.type = type;
this.ds = ds;
ctr = 0;
}
Using the constructor we initialize a ListItemType
and DataSet
instance variable. The ListItemType
variable represents the current template while the DataSet
holds the data to be displayed on the Repeater control.
We have to implement the InstantiateIn
function passing a Control
object as a parameter. Within the InstantiateIn
method, we must check the current template and accordingly store the relevant HTML code in a LiteralControl
.
Finally, we must add the literal control to the controls collection of the Repeater:
public void InstantiateIn(Control container)
{
switch (type) // Check the template type
{
case ListItemType.Header: // Header Template
lc = new LiteralControl("<table border='5'><
tr bgcolor='red'><th>Empno</th><th>Name</th></tr>");
break;
case ListItemType.Item: // Item Template
lc = new LiteralControl("<tr bgcolor='yellow'><
td>" + ds.Tables["emp"].Rows[ctr]["empno"] + "</td><td>" +
ds.Tables["emp"].Rows[ctr]["empname"] + "</td></tr>");
ctr++;
break;
case ListItemType.AlternatingItem: // AlternatingItem Template
lc = new LiteralControl("<tr bgcolor='lime'><td>" +
ds.Tables["emp"].Rows[ctr]["empno"] + "</td><td>" +
ds.Tables["emp"].Rows[ctr]["empname"] + "</td></tr>");
ctr++;
break;
case ListItemType.Footer: // Footer Template
lc = new LiteralControl("</table>");
ctr = 0;
break;
}
container.Controls.Add(lc);
}
Note: For simplicity, I have created ItemTemplate
and AlternatingItemTemplate
for only two columns, i.e., empno
and empname
.
In our ASP.NET page in the Page_Load
event, we implement DataBinding
to bind data from the data source to the Repeater control and apply the templates:
Data Binding
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(); // Creating a connection
con.ConnectionString = @"Data Source=servername;Initial Catalog=databasename;
User ID=username;Password=password"; // SQL Connection String
// to connect to database
SqlCommand cmd = new SqlCommand(); // Creating a command
cmd.Connection = con;
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from emp";
SqlDataAdapter da = new SqlDataAdapter(); // Creating a data adapter.
da.SelectCommand = cmd;
DataSet ds = new DataSet(); // Creating a DataSet
con.Open();
da.Fill(ds, "emp");
con.Close();
Applying Templates
Repeater1.DataSource = ds.Tables["emp"];
Repeater1.HeaderTemplate = new MyTemplate(ListItemType.Header, null);
Repeater1.ItemTemplate = new MyTemplate(ListItemType.Item, ds);
Repeater1.AlternatingItemTemplate = new MyTemplate(ListItemType.AlternatingItem, ds);
Repeater1.FooterTemplate = new MyTemplate(ListItemType.Footer, null);
Repeater1.DataBind();
Points of Interest
Initially, I was unable to figure out how to display data from a database, then I realized that I can pass a DataSet
parameter to the constructor of the inherited template class and retrieve the data table, data row and data column and use them in ItemTemplate
and AlternatingItemTemplate
.
History
- 8th May, 2011: Initial post