Introduction:
The Data controls play significant role in the application development. It helps developers to write the minimal code to achieve the expected results. Otherwise it will be more tedious to write everything for the data controls. The data control supports to use another data controls inside the control. I have illustrated an example of DataList control inside the Repeater control. Let us see.
Background:
The data controls can be bind with the DataSet. The table result set can be assigned to the data controls like Repeater. I have taken the repeater control for display the main records. I have chosen the Northwind database for demonstrate this approach. There the Products table will be available. All the products details will be bind with the Repeater control. I want to display the product sales report when I click to expand button in the every product, then it will expand and show the report of the sale details. For that I have used the DataList control.
<!--[if !vml]-->
<!--[endif]-->
Here the Repeater is the parent control and DataList is the child control for display the sale report.
If you expand the product row, then it will show the Product sales details in the DataList control.
<!--[if !vml]-->
Data Controls in Data Controls:
First, we have to design the Parent control and inside that we can write another data controls. The parent control can be bind with the table results. Now we have to bind the sub report part in the parent control. We have to design the child data control like parent control. In the server side event I have written the OnItemDataBound event to find the control of child data control.
I have retrieved the result set for the child control and bind to the data control. Here, if you want to write the server side events for the child control like OnItemDataBound or OnItemCommand then we have to define the event in the control tag.
Let us see the server side event of the Parent control repeater.
protected void rptProducts_OnItemDatabound(object sender, RepeaterItemEventArgs e)
{
try
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Label lblProductID = (Label)e.Item.FindControl("lblProductID");
DataList dlProductSales = (DataList)e.Item.FindControl("dlProductSales");
LinkButton lbtnView = (LinkButton) e.Item.FindControl("lbtnView");
Label lblMsg = (Label)e.Item.FindControl("lblMsg");
if (lblProductID.Text.Trim() != null)
{
lbtnView.Attributes.Add("OnClick", "window.top.location.href='SalesView.aspx?ProductID="+lblProductID.Text.ToString()+"';return false;");
DataSet oDataSet = oBusinessLogics.RetrieveProductSales(Convert.ToInt32(lblProductID.Text.ToString()));
if (oDataSet != null)
{
if (oDataSet.Tables[0].Rows.Count > 0)
{
dlProductSales.DataSource = oDataSet.Tables[0];
dlProductSales.DataBind();
}
}
}
}
}
catch (Exception oEx)
{
Response.Write(oEx.Message);
}
}
There, what I have done is searched the child control and bind that using the DataSet.
If you want to write the server side event for the child control then you can write the following way.
protected void dlProductSales_OnItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
Label lblOrderID = (Label)e.Item.FindControl("lblOrderID");
LinkButton lbtnOrderView = (LinkButton)e.Item.FindControl("lbtnOrderView");
if (lblOrderID.Text.Trim() != null)
{
lbtnOrderView.Attributes.Add("OnClick", "window.location.href='OrdersView.aspx?OrderID="+lblOrderID.Text.Trim()+"';return false;");
}
}
}
Designing of the Nested Data Controls:
The parent control is desgined using the Repeater control and the child control have designed in the DataList control.
In the Item template, I have used the another data control DataList.
<asp:Repeater ID="rptProducts" runat="server" OnItemDataBound="rptProducts_OnItemDatabound">
<HeaderTemplate>
<table cellpadding="0" cellspacing="0" border="1" width="100%">
<tr style="font-weight: bold; text-align: center; color: silver;" class="LinkButton">
<td style="width: 5%;">
Expand/Collapse
</td>
<td style="width: 10%;">
Product ID
</td>
<td style="width: 10%;">
Product Name
</td>
<td style="width: 10%;">
Supplier ID
</td>
<td style="width: 10%;">
Category ID
</td>
<td style="width: 10%;">
Qty per unit
</td>
<td style="width: 10%;">
Price
</td>
<td style="width: 10%;">
Stocks
</td>
<td style="width: 10%;">
View
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr style="text-align: center;">
<td style="width: 5%;">
<asp:Image ID="imgExpCol" Style="cursor: pointer;" onclick="return ExpandCollapse(this); runat="server" ImageUrl="~/Pages/plus.gif" />
</td>
<td style="width: 10%;">
<asp:Label ID="lblProductID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"ProductID") %>'></asp:Label>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"ProductName") %>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"SupplierID") %>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"CategoryID") %>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"QuantityPerUnit") %>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"UnitPrice") %>
</td>
<td style="width: 10%;">
<%# DataBinder.Eval(Container.DataItem,"UnitsInStock") %>
</td>
<td style="width: 10%;">
<asp:LinkButton ID="lbtnView" CssClass="LinkButton" runat="server" Text="View"></asp:LinkButton>
</td>
</tr>
<tr id="TrProductSales" runat="server" style="display: none;">
<td colspan="9" align="center">
<asp:DataList ID="dlProductSales" BackColor="lightgray" Width="100%" runat="server"
RepeatColumns="1" RepeatDirection="Horizontal" RepeatLayout="Table" OnItemDataBound="dlProductSales_OnItemDataBound">
<HeaderTemplate>
<table cellpadding="0" cellspacing="0" border="1" width="100%">
<tr style="color: black; text-align: center;">
<td style="width: 15%;">
Order ID
</td>
<td style="width: 15%;">
Product ID
</td>
<td style="width: 20%;">
Unit Price
</td>
<td style="width: 20%;">
Quantity
</td>
<td style="width: 20%;">
Discount
</td>
<td style="width: 10%;">
View Order
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr style="color: Navy; text-align: center;">
<td style="width: 15%;">
<asp:Label ID="lblOrderID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"OrderID") %>'></asp:Label>
</td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"ProductID") %>
</td>
<td style="width: 20%;">
<%# DataBinder.Eval(Container.DataItem,"UnitPrice") %>
</td>
<td style="width: 20%;">
<%# DataBinder.Eval(Container.DataItem,"Quantity") %>
</td>
<td style="width: 20%;">
<%# DataBinder.Eval(Container.DataItem,"Discount") %>
</td>
<td style="width: 10%;">
<asp:LinkButton ID="lbtnOrderView" CssClass="LinkButton"
runat="server" Text="View"></asp:LinkButton>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:DataList>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Future Implementation:
I have one suggestion in this application. What I have done is, I have generated the report for all the products. When click on the expand icon then it shows the report.I have used the JavaScript for handling the expand/collapse. Instead of that, when click on the expand button, it has to bind the result set of the child control. It can be done using the ItemCommand event in the server side.It will give you better performance. Because this current approach will give more overhead to the server. Suppose if you have lakhs records then it has to bind the all sub report. Instead that it has to be loaded on the demand basis.
Conclusion:
we have seen the nested data controls in the ASP.Net application. I have attached the source code of this demo application. I hope that it will give you some idea about the nested data controls usage in the ASP.Net.