Click here to Skip to main content
15,867,756 members
Articles / Web Development / ASP.NET
Article

Creating a Templated User Control

Rate me:
Please Sign up or sign in to vote.
4.77/5 (25 votes)
2 Dec 2007CPOL4 min read 123K   1.8K   54   12
This article explains how to create your own repeater, with templates.

Introduction

The Modern Web programming technology ASP.NET provides many tools and controls to develop Web applications rapidly. For example, the Repeater control is a really simple and powerful control which renders collection data into a web page within a short time of coding. Imagine you want to do the same in classic ASP or PHP, you may have to write a loop in ASP with combined HTML and server scripts. The first difference between ASP and ASP.NET is separation of HTML and server scripts. Microsoft has provided many controls to play with data, for example: Repeater, DataGridView, DataList etc. In this article I am going to explain how to create this kind of Templated data control.

Selecting a Proper Scenario

Creating a custom control every time is an expense of time. In addition, it may not be tested properly in all kinds of scenarios. It's always the best approach to select the control like DataReader which is provided and tested by Microsoft itself. However, in some scenarios we may need better functionality and customization of the control. In such a kind of scenario, we go for UserControl [or] CustomControl development.

In this article, I am going to explain a typical DataRepeater development. Even though it's already available in ASP.NET, we are going to create a control like Repeater only (Repeating Repeater), because we are already familiar with Repeater controls functionality and it's templates, so it will be easy to understand.

Planning the Control

Since we are going to create a control like DataRepeater, planning about the control is easy. I am going to change only the name of the control. The name of the control is MyRepeater, which consists of the following four templates:

  • Header template
  • Footer template
  • Item template
  • Alternate item template

As we already know, the Header and Footer should be rendered once, and the count of Item template and AlternateItemTemplate should be equal to the number of items in the DataSource.

Planning the DataSource

Like Repeater, our control should also support most of the generic types, like the ones given below:

  • DataTable
  • DataView
  • List
  • Collection
  • ArrayList
  • Array

Don't get confused about how to handle all the above data types inside the control. This is really simple. All the above data types internally implement IEnumerable, so if we develop a control for IEnumerable, that will support all the above data sources.

Important Data Types

We are going to use the following important data types to develop our own Repeater, please refer to MSDN for a detailed description of the following types:

  • ITemplate
  • IEnumerable
  • INamingContainer
  • IDataItem
  • Control

Creating the User Control

Create a new user control named MyRepeater.ascx, and refer the same in Default.aspx. So default.aspx & MyRepeater.ascx will look like they are shown below:

MyRepeater.ascx

ASP.NET
<%@ Control Language="C#" AutoEventWireup="true"
    CodeFile="MyRepeater.ascx.cs" Inherits="MyRepeater" %>

Default.aspx

ASP.NET
<%@ Page Language="C#" AutoEventWireup="true"
    CodeFile="Default.aspx.cs" Inherits="_Default" %>

<%@ Register Src="MyRepeater.ascx" TagName="MyRepeater" TagPrefix="myOwn" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>

</head>
<body>
    <form id="form1" runat="server">
    <div>
        <myOwn:MyRepeater ID="MyRepeater1" runat="server">
        </myOwn:MyRepeater>

    </div>
    </form>
</body>
</html>

Creating Templates

By default, UserControl doesn't have any templates inside, so we have to create public properties to enable templates for the UserControl. Create the following four public properties inside the UserControl.

MyRepeater.ascx.cs

C#
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections;
public partial class MyRepeater : System.Web.UI.UserControl
{
    private ITemplate _ItemTemplate;
    private ITemplate _AlternateItemTemplate;
    private ITemplate _HeaderTemplate;
    private ITemplate _FooterTemplate;
    private IEnumerable _DataSource;

    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [TemplateContainer(typeof(SimpleTemplateItem))]
    public ITemplate ItemTemplate
    {
        get { return _ItemTemplate; }
        set { _ItemTemplate = value; }
    }

    [TemplateContainer(typeof(SimpleTemplateItem))]
    public ITemplate AlternateItemTemplate
    {
        get { return _AlternateItemTemplate; }
        set { _AlternateItemTemplate = value; }
    }

    [TemplateContainer(typeof(SimpleTemplateItem))]
    public ITemplate HeaderTemplate
    {
        get { return _HeaderTemplate; }
        set { _HeaderTemplate = value; }
    }

    [TemplateContainer(typeof(SimpleTemplateItem))]
    public ITemplate FooterTemplate
    {
        get { return _FooterTemplate; }
        set { _FooterTemplate = value; }
    }
 }
  • ITemplate: This is an interface provided by ASP.NET, which is used to hold the specific template content.
  • TemplateContainer: This attribute is used to provide the type of the template content.

For each template, runtime must create a UserControl instance to hold the contents, for instance, if your DataSource has 100 records, internally 100 instances of templates will be created. We need to create another UserControl to render each template into that. This control is called the template container control. Create the class/control as follows:

SimpleTemplateItem.cs

C#
public class SimpleTemplateItem :
    Control, System.Web.UI.INamingContainer, IDataItemContainer
{
    private object _CurrentDataItem;
    public SimpleTemplateItem(object currentItem)
    {
        _CurrentDataItem = currentItem;

    }

    #region IDataItemContainer Members

    public object DataItem
    {
        get { return _CurrentDataItem; }
    }

    public int DataItemIndex
    {
        get { throw new Exception
            ("The method or operation is not implemented."); }
    }

    public int DisplayIndex
    {
        get { throw new Exception
            ("The method or operation is not implemented."); }
    }

    #endregion
}
  • INamingContainer: This is a Marker interface — it doesn't have any methods, or properties inside — this is just to provide control id in the runtime.
  • IDataItem: Properties of IDataItem are used to hold the single item of the DataSource with respect to the template instance.

Adding Code to Render the Templates

As of now, we created a UserControl with four template properties and another UserControl (template container) to render the templates on it. Now we need to add the code logic to render the templates. ITemplate interface internally has a method called InstantiateIn, which is used to render the template content into the desired control. Add the following codes into the databind method of myrepeater class, which will add the templates to the UserControl.

MyRepeater.ascx.cs [Databind Method]

C#
public override void DataBind()
   {
       //Rendering Header template into current control
       AddTemplateAsControl(HeaderTemplate, null);

       IEnumerator ie = DataSource.GetEnumerator();
       bool renderAlternateTemplate = false;

       while (ie.MoveNext())
       {


           if (renderAlternateTemplate && AlternateItemTemplate != null)
           {

               AddTemplateAsControl(ItemTemplate, ie.Current);
           }
           else if (AlternateItemTemplate != null)
           {
               AddTemplateAsControl(AlternateItemTemplate,ie.Current);
           }
           else
           {
               //don't render anything
           }

           renderAlternateTemplate = !renderAlternateTemplate;
       }

       //Rendering footer template into current control
       AddTemplateAsControl(FooterTemplate, null);

       //Always better to call base class implementation
       base.DataBind();
   }

   private void AddTemplateAsControl(ITemplate anyTemplate,object cuurentItem)
   {
       SimpleTemplateItem templateContentHolder = new SimpleTemplateItem(cuurentItem);
       anyTemplate.InstantiateIn(templateContentHolder);
       this.Controls.Add(templateContentHolder);
   }

Testing MyRepeater

To test the Repeater, create any DataSource and bind to the UserControl. Below is the sample code to test the Repeater.

Default.aspx

ASP.NET
<myOwn:MyRepeater ID="MyRepeater1" runat="server">

        <HeaderTemplate>
            Customer List:
            <table border="1">
                <tr><th>Id</th><th>Name</th><th>Location</th></tr>

        </HeaderTemplate>

        <ItemTemplate>
            <tr style="background-color:gold">
            <td><%#DataBinder.Eval(Container.DataItem,"Id") %></td>
            <td><%#DataBinder.Eval(Container.DataItem,"Name")%></td>

            <td><%#DataBinder.Eval(Container.DataItem,"Location") %></td>
            </tr>
        </ItemTemplate>

        <AlternateItemTemplate>
            <tr><td><%#DataBinder.Eval(Container.DataItem,"Id") %></td>

            <td><%#DataBinder.Eval(Container.DataItem,"Name")%></td>
            <td><%#DataBinder.Eval(Container.DataItem,"Location") %></td>
            </tr>
        </AlternateItemTemplate>

        <FooterTemplate>
            </table>
            </FooterTemplate>

    </myOwn:MyRepeater>

Default.aspx.cs

C#
using System;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections.Generic;

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        List<Customer> customerList = new List<Customer>();

        customerList.Add(new Customer("Prem", "New york"));
        customerList.Add(new Customer("Jhon", "Amsterdam"));
        customerList.Add(new Customer("Peter", "London"));
        customerList.Add(new Customer("Mani", "Chennai"));
        customerList.Add(new Customer("Paul", "Paris"));

        MyRepeater1.DataSource = customerList;
        MyRepeater1.DataBind();
    }
}

public class Customer
{
    private string _Name;
    private Guid _Id;
    private string _Location;

    public Customer(string name, string location)
    {
        this.Name = name;
        this.Location = location;
        this.Id = Guid.NewGuid();
    }

    public string Name
    {
        get { return _Name; }
        set { _Name = value; }
    }

    public Guid Id
    {
        get { return _Id; }
        set { _Id = value; }
    }

    public string Location
    {
        get { return _Location; }
        set { _Location = value; }
    }
}

Conclusion

I hope you understood how to develop your own Templated control like DataGrid, DataList etc. with the addition of your own features. Instead of the SimpleTemplateItem class, you can also use the existing RepeaterItem class if you do not require any additional features. The control that we created is very lightweight, like a normal Repeater. If you want, you can also add some extra features like paging, sorting, etc.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
India India
"Manikandan Balakrishnan" Working as an IT consultant with LogicaCMG’s Global Service Delivery part-India, he has a good experience on Web/Win development (C#, Asp.net) and enterprise application integration (BizTalk) technologies. Prior to this he worked on world’s biggest e-learning product with Excel Soft Technologies, Mysore.

City: Coimbatore, TN
CreativeManix@gmail.com

Comments and Discussions

 
Questionvisual studio intellisense not working Pin
Girish Nama28-Mar-14 16:29
Girish Nama28-Mar-14 16:29 
GeneralMy vote of 1 Pin
Igor Sukhov9-Mar-12 0:26
Igor Sukhov9-Mar-12 0:26 
GeneralGood Job Thank you Pin
Mayank P Kukadia6-Jan-12 1:19
Mayank P Kukadia6-Jan-12 1:19 
QuestionAdding a control with runat server Pin
dilipms31-Oct-11 1:43
dilipms31-Oct-11 1:43 
GeneralMy vote of 4 Pin
Huseyin OZCAKIR29-Aug-10 12:18
Huseyin OZCAKIR29-Aug-10 12:18 
QuestionA bug Pin
Dimitri Witkowski1-Jun-10 5:56
Dimitri Witkowski1-Jun-10 5:56 
Generalgreate one Pin
Sbusiso3-Mar-10 0:22
Sbusiso3-Mar-10 0:22 
GeneralNice example -- missing a property Pin
rcaciopp11-Jul-09 3:26
rcaciopp11-Jul-09 3:26 
GeneralRe: Nice example -- missing a property Pin
Manikandan.net12-Jul-09 18:42
Manikandan.net12-Jul-09 18:42 
Thanks rcaciopp,

Actully I missed it Smile | :)

Manikandan.net
[Coding is life]

QuestionError Creating Control? Pin
xinhongrao26-Apr-08 18:46
xinhongrao26-Apr-08 18:46 
GeneralRe: Error Creating Control? Pin
Manikandan.net27-Apr-08 18:38
Manikandan.net27-Apr-08 18:38 
GeneralGood job ! Pin
Dav Zen12-Dec-07 23:23
Dav Zen12-Dec-07 23:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.