Introduction:
In this article, I will be explaining about the sub report in the grid view. I took northwind database as example for this demonstration.
GridView with Sub report:
The product will have the sale order details. The entire product with the details will be displayed one by one. Here the every product may have the sale order details in the other table. If you want to show the product sale underneath of the main products then it will be little bit tedious. The server side another data control must be placed in the every row of the result in the main gridview.
I will be explaining the Gridview with inside the GridView. Here I have implemented in a different way which will retrieve the result very quickly. I have used the Ajax technique to retrieve the result of the every product sale.
When click on the every product expand it will load the data for the corresponding product from the database using the Ajax.
<asp:GridView CssClass="Table" ID="gvProducts" AllowPaging="true" PageSize="10" BorderStyle="Solid" GridLines="Both" BorderColor="White" OnPageIndexChanging="gvProducts_PnPageIndexChanging" BorderWidth="1px" runat="server" AutoGenerateColumns="false">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr style="text-align: center;">
<td style="width:2%;"></td>
<td style="width: 16%;">Product ID</td>
<td style="width: 18%;">Product Name</td>
<td style="width: 15%;">Supplier ID</td>
<td style="width: 15%;">Category ID</td>
<td style="width: 19%;">Quantity/Unit</td>
<td style="width: 15%;">Unit Price</td>
<td style="width: 15%;">Unit Stock</td>
</tr>
</table>
</HeaderTemplate>
<ItemTemplate>
<table cellpadding="0" cellspacing="0" border="0" width="100%">
<tr style="text-align: center;">
<td style="width:2%;">
<img id="imgPlusMinus" style="cursor:pointer;" onclick="return Expand(this);" runat="server" src="~/Common/Images/plus.gif" />
</td>
<td style="width: 15%;">
<asp:Label ID="lblProductID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem,"ProductID") %>'></asp:Label></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"ProductName") %></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"SupplierID") %></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"CategoryID") %></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"QuantityPerUnit") %></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"UnitPrice") %></td>
<td style="width: 15%;">
<%# DataBinder.Eval(Container.DataItem,"UnitsInStock") %></td>
</tr>
<tr style="display: none;" id="TrOrders" runat="server">
<td colspan="7">
<div id="divOrderDetails" runat="server">
</div></td></tr>
</table>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<PagerStyle ForeColor="Orange" />
</asp:GridView>
I have added one more row for display the sub report content in this part. That will be hidden initially. I have used the div tag inside that every row for display the content.
<script type="text/javascript">
function Expand(Ctrl)
{
var imgPlusMinus = Ctrl.id;
var _TrID = imgPlusMinus.replace("imgPlusMinus", "TrOrders");
var lblProductID = imgPlusMinus.replace("imgPlusMinus", "lblProductID");
var _divOrderDetails = imgPlusMinus.replace("imgPlusMinus", "divOrderDetails");
var _ProductID = document.getElementById(lblProductID).innerHTML;
var _QueryString = "";
_QueryString = "PRID=" + _ProductID;
if (document.getElementById(_TrID).style.display == '') {
document.getElementById(_TrID).style.display = 'none';
document.getElementById(imgPlusMinus).src = "../../Common/Images/plus.gif";
}
else {
document.getElementById(_TrID).style.display = '';
document.getElementById(imgPlusMinus).src = "../../Common/Images/minus.gif";
}
var xmlHttp;
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
document.getElementById(_divOrderDetails).innerHTML =
xmlHttp.responseText;
}
}
}
xmlHttp.open("GET", "AjaxPage.aspx?" + _QueryString, true);
xmlHttp.send(null);
return false;
}
</script>
The product id will be sent to the Ajax call page.Based on the id the sales of the products will be formed as HTML table content and that will be returned to the main page. After succession of the HTML content the data will be displayed as subreport in the corresponding product row.
Sub report formation in the Ajax call page.
strHTML = "<table cellpadding='0' cellspacing='0' border='1' width='100%'>";
strHTML += "<tr style='color:orange;'>";
strHTML += "<td>Order ID</td>";
strHTML += "<td>Product ID</td>";
strHTML += "<td>Unit Price</td>";
strHTML += "<td>Quantity</td>";
strHTML += "<td>Discount</td>";
strHTML += "</tr>";
if (dsProdSales.Tables[0].Rows.Count == 0)
{
strHTML += "<tr style='color:yellow;'>";
strHTML += "<td colspan='5' style='text-align:center;'>No records found.</td>";
strHTML += "<tr/>";
}
else
{
for (int index = 0; index < dsProdSales.Tables[0].Rows.Count; index++)
{
strHTML += "<tr style='color:yellow;'>";
strHTML += "<td>" + dsProdSales.Tables[0].Rows[index]["OrderID"].ToString() + "</td>";
strHTML += "<td>" + dsProdSales.Tables[0].Rows[index]["ProductID"].ToString() + "</td>";
strHTML += "<td>" + dsProdSales.Tables[0].Rows[index]["UnitPrice"].ToString() + "</td>";
strHTML += "<td>" + dsProdSales.Tables[0].Rows[index]["Quantity"].ToString() + "</td>";
strHTML += "<td>" + dsProdSales.Tables[0].Rows[index]["Discount"].ToString() + "</td>";
strHTML += "</tr>";
}
}
Sample Screens:
The following are the sample screens.
1(a). The main grid with the product details.
1(b) The Sub report of the product after expand
Conclusion:
I hope that this will be very useful in the sub report implementation. If you have any issues or doubts in this please email me.I have attached the source code of this application. Please post your valuable suggestions.