Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Nesting data bound (Repeater) controls in ASP.NET

3.90/5 (8 votes)
26 Aug 2007CPOL2 min read 4   1.1K  
This article is about nesting data bound controls like Repeater, Grid, etc.

Introduction

This article shows how to nest the Repeater control in ASP.NET pages to any level. Using the same way, you can nest other data bound controls like DataGrid, GridView, and DataList.

Using the code

There is always a need for web developers to connect to different kinds of databases and extract information from there and present it in an organized form on web pages. ASP.NET provides data access controls to connect with external data sources. It also provides several UI controls to present that information in an organized way.

The Repeater control is one of the controls used for the above-mentioned purpose. It is specially designed to work with data tables but can be used with other data sources also.

The Repeater control can be used for editing databases as well as for displaying data on web pages.

The focus of this article is on nesting data bound controls. I have used the Repeater control as an example here. By following the same pattern, you can nest any other data bound control up to your desired level. The most important thing to know here is the events and the order of the events.

In this article, I have nested the Repeater control up to two levels but I think you can use the technique to nest to any level.

First, let me explain why we have to nest data bound controls. Suppose we have unlimited address types and you can add unlimited address to each type of address. To present the address according to address type, we need to nest a Repeater control.

The design of my page with an explanation of the important things is shown here:

ASP.NET
<asp:Repeater id="RepeaterAdd" runat="server">
<ItemTemplate>
    <div>
         <asp:Label ID="lblHead" runat="server" CssClass="level2">
              <%# DataBinder.Eval(Container.DataItem, "LKI_NAME") %>
                   Addresses:
         </asp:Label>
    </div>

    //Here LKI_NAME contain Address Types description like "Home", 
    // "Office" etc         <br />
    //Here I have nested Child Repeater control inside my main repeater. 
    // Main repeater "RepeaterAdd" contains address types while repeater 
    // "Rchild" contains address related to each address type.
    <asp:Repeater ID="Rchild" runat="server">
    <ItemTemplate>
        <asp:Label ID="Label1" runat="server" CssClass="modulebox" 
            Width="100">Address Line1:</asp:Label>  
        <asp:Label ID="lbl1" runat="server" CssClass="moduleBoxBlack">
            <%# DataBinder.Eval(Container.DataItem, "ADR_ADDRESSL1") %>
        </asp:Label>
        <br />
            <asp:Label ID="Label2" runat="server" CssClass="modulebox"
                Width="100">Address Line2:</asp:Label></b>   
            <asp:Label ID="lbl2" runat="server" CssClass="moduleBoxBlack">
                <%# DataBinder.Eval(Container.DataItem, "ADR_ADDRESSL2")%>
            </asp:Label>
        <br />
            <asp:Label ID="Label4" runat="server" CssClass="modulebox" 
                Width="100">City Name:</asp:Label>  
            <asp:Label ID="lbl4" runat="server" CssClass="moduleBoxBlack">
                <%# DataBinder.Eval(Container.DataItem, "ADR_CITYNAME") %>
            </asp:Label>
        <br />
            <asp:Label ID="Label3" runat="server" CssClass="modulebox" 
                Width="100">State:</asp:Label>  
            <asp:Label ID="lbl3" runat="server" CssClass="moduleBoxBlack">
                <%# DataBinder.Eval(Container.DataItem, "ADR_STATENAME")%>
            </asp:Label>
        <br />
            <asp:Label ID="Label5" runat="server" CssClass="modulebox" 
                Width="100">Postal Code:</asp:Label>  
            <asp:Label ID="lbl5" runat="server" CssClass="moduleBoxBlack">
                <%# DataBinder.Eval(Container.DataItem,"ADR_POSTALCODE")%>
            </asp:Label>
        <br />
            <asp:Label ID="Label6" runat="server" CssClass="modulebox" 
                Width="100">Country:</asp:Label>              
            <asp:Label ID="lbl6" runat="server" CssClass="moduleBoxBlack">
                <%# DataBinder.Eval(Container.DataItem, "CNT_NAME") %>
            </asp:Label>    
            <asp:LinkButton Runat="server" ID="LnkEdit" 
                CssClass="LinkBtn">Edit</asp:LinkButton>
                    
            <asp:LinkButton Runat="server" ID="lnkDelete" 
                CommandName="DeleteMe" 
                CommandArgument='<%# DataBinder.Eval(Container.DataItem, 
                "ADR_ID") %>' CssClass="LinkBtn">Delete</asp:LinkButton>
        <br /><br />
    </ItemTemplate>
</asp:Repeater><br />  
<asp:Button ID="btnAdd" Text="Add" runat="server" 
         CssClass="button" CommandName="OpenPopup" />
    <br /><br /><br />         
</ItemTemplate></asp:Repeater>

Points of Interest

The most important thing here is to know about the events and their order of occurrence. The three very basic but most powerful events of data bound controls are ItemCreated, ItemCommand, and ItemDatabound. One must know well about how to handle these events in order to meet this cutting edge requirement of data presentation.

First, let me explain the ItemCreated event that actually does the trick of capturing nested (internal) Repeater events. The code for that event is:

C#
private void RepeaterAdd_ItemCreated(object sender, 
             System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
    Repeater r = ((Repeater)e.Item.FindControl("Rchild"));
    r.ItemCommand += new RepeaterCommandEventHandler(
        this.RepeaterInner_ItemCommand);
    r.ItemDataBound += new RepeaterItemEventHandler(
        this.RepeaterInner_ItemDataBound);
}

Secondly, we need to bind the data with our inner Repeater. Where do we do it? Of course, the ItemDatabound of the outer Repeater is the best place to do that.

C#
private void RepeaterAdd_ItemDataBound(object sender, 
        System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || 
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        DataRowView drv = (DataRowView)e.Item.DataItem;
        string AddressType = drv["LKI_NAME"].ToString();
        string AddressTypeId = drv["LKI_ID"].ToString();
        //DataTable dt = new DataTable();
        //Bind your inner repeater here.
        Repeater r = ((Repeater)e.Item.FindControl("Rchild"));
        r.DataSource = dt; //Suppose dt is the data table to bind.
        r.DataBind();
        //Bind the add button here.
        Button btn = ((Button)e.Item.FindControl("btnAdd"));
        btn.Attributes["onclick"] = 
            string.Format("return ShowAddressForm('{0}','{1}',
            '{2}');", "Add", AddressType, AddressTypeId);
    }
}

At this stage, we have already completed with our basic steps. The only remaining step is how to capture the commands. ItemCommand is the event we have to play with. Below is an example of handling the inner Repeater commands.

C#
private void RepeaterInner_ItemCommand(object source, 
        System.Web.UI.WebControls.RepeaterCommandEventArgs e)
{
    strin cmdArgument = e.CommandArgument.ToString();
    if (e.CommandName == "EditMe")
    {
        // Do Edit Link Operation here.
    }
    else if (e.CommandName == "DeleteMe")
    {
        //Do Delete Link Opearation here.
    }
}

Hopefully this article will help you understand how to nest data bound controls.

Conclusion

Data bound controls like Repeater, DataList, GridView, and DataGrid can nest data to any level by following the same procedure. Happy programming you guys.

License

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