In this article I will explain with an example, how to implement
Nested Repeater controls i.e.
Child Repeater inside
Parent Repeater with example in
ASP.Net using C# and VB.Net.
In this example of
Nested Repeaters, the
parent Repeater is populated with
Customer records and the
Child Repeater will be populated
Orders for each
Customer when the
Expand icon is clicked.
Database
Here I am making use of Microsoft’s Northwind Database. You can download it from here.
HTML Markup
The following
HTML Markup consists of:
Repeater – For displaying the records.
The
Repeater has the following Templates:
HeaderTemplate
The content of this template will not be
repeated and will be placed in the top most position i.e. head section of the
Repeater control.
ItemTemplate
Panel – For group multiple control in one place.
Repeater – For displaying the records.
The
Repeater has the following Templates:
HeaderTemplate
The content of this template will not be repeated
ItemTemplate
The
ItemTemplate consists of
Label controls which use for display text.
FooterTemplate
The content of this template will not be
repeated and will be placed in the bottom most position i.e. footer section of the
Repeater control.
<form id="form1" runat="server">
<asp:Repeater ID="rptCustomers" runat="server" OnItemDataBound="OnItemDataBound">
<HeaderTemplate>
<table class="Grid" cellspacing="0" rules="all" border="1">
<tr>
<th scope="col"> </th>
<th scope="col" style="width: 150px">Contact Name</th>
<th scope="col" style="width: 150px">City</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<img alt="" style="cursor: pointer" src="images/plus.png" />
<asp:Panel ID="pnlOrders" runat="server" Style="display: none">
<asp:Repeater ID="rptOrders" runat="server">
<HeaderTemplate>
<table class="ChildGrid" cellspacing="0" rules="all" border="1">
<tr>
<th scope="col" style="width: 150px">Order Id</th>
<th scope="col" style="width: 150px">Date</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><asp:Label ID="lblOrderId" runat="server" Text='<%# Eval("OrderId")%>' /></td>
<td><asp:Label ID="lblOrderDate" runat="server" Text='<%# Eval("OrderDate")%>' /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</asp:Panel>
<asp:HiddenField ID="hfCustomerId" runat="server" Value='<%# Eval("CustomerId")%>' />
</td>
<td><asp:Label ID="lblContactName" runat="server" Text='<%# Eval("ContactName")%>' /></td>
<td><asp:Label ID="lblCity" runat="server" Text='<%# Eval("City")%>' /></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Namespaces
You will need to import the following namespaces.
C#
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
VB.Net
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Binding the Customers records to the Parent Repeater
Inside the
Page Load event handler, the parent
Repeater is populated with the records of
Customers table from the Northwind Database.
C#
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
rptCustomers.DataSource = GetData("SELECT TOP 10 * FROM Customers");
rptCustomers.DataBind();
}
}
private static DataTable GetData(string query)
{
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = query;
using (SqlDataAdapter sda = new SqlDataAdapter())
{
cmd.Connection = con;
sda.SelectCommand = cmd;
using (DataSet ds = new DataSet())
{
DataTable dt = new DataTable();
sda.Fill(dt);
return dt;
}
}
}
}
}
VB.Net
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
If Not Me.IsPostBack Then
rptCustomers.DataSource = GetData("SELECT TOP 10 * FROM Customers")
rptCustomers.DataBind()
End If
End Sub
Private Shared Function GetData(query As String) As DataTable
Dim constr As String = ConfigurationManager.ConnectionStrings("constr").ConnectionString
Using con As New SqlConnection(constr)
Using cmd As New SqlCommand()
cmd.CommandText = query
Using sda As New SqlDataAdapter()
cmd.Connection = con
sda.SelectCommand = cmd
Using ds As New DataSet()
Dim dt As New DataTable()
sda.Fill(dt)
Return dt
End Using
End Using
End Using
End Using
End Function
Binding the Child Repeater with the Orders for each Customer in the Parent Repeater
Inside the
OnItemDataBound event handler, the parent
Repeater control, first the reference child (nested)
Repeater control and the
CustomerId HiddenField is determined and then the
CustomerId value is fetched from the
HiddenField and is used to populate the child (nested)
Repeater control with the records of the
Orders Table of the Northwind Database.
Note: GetData is a generic function and the same function discussed above is used here.
C#
protected void OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
string customerId = (e.Item.FindControl("hfCustomerId")as HiddenField).Value;
Repeater rptOrders = e.Item.FindControl("rptOrders")as Repeater;
rptOrders.DataSource = GetData(string.Format("SELECT TOP 3 * FROM Orders WHERE CustomerId='{0}'", customerId));
rptOrders.DataBind();
}
}
VB.Net
Protected Sub OnItemDataBound(sender As Object, e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
Dim customerId As String = TryCast(e.Item.FindControl("hfCustomerId"), HiddenField).Value
Dim rptOrders As Repeater = TryCast(e.Item.FindControl("rptOrders"), Repeater)
rptOrders.DataSource = GetData(String.Format("SELECT TOP 3 * FROM Orders WHERE CustomerId='{0}'", customerId))
rptOrders.DataBind()
End If
End Sub
Client side Expand Collapse functionality using jQuery and JavaScript
First, the following script file is inherited
1. jquery.min.js
Inside the
document ready event handler, the
Expand and
Collapse of the child (nested)
Repeater control,
jQuery has been used. A
jQuery event handler has been assigned to the each
Expand (Plus) and
Collapse (Minus) Image elements.
When the
Expand (Plus) image element is
clicked, the child (nested)
Repeater control is shown using a dynamic
Table Row within the
parent Repeater control.
Finally, when the Collapse (Minus) Image element is clicked, the dynamic
Table Row is removed.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script type="text/javascript">
$("body").on("click", "[src*=plus]", function () {
$(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>")
$(this).attr("src", "images/minus.png");
});
$("body").on("click", "[src*=minus]", function () {
$(this).attr("src", "images/plus.png");
$(this).closest("tr").next().remove();
});
</script>
Screenshot
Demo
Downloads