Home
Products
Forums
Help
Publish Article
Go Freelance

Embed ASP.Net DataGrid Control Inside Another DataGrid Control

We have been trying to bring you some basic to advanced techniques that you can use to format the view for ASP.Net DataGrid control. In the same series we bring you another article that will show how you can exploit the flexible architecture of DataGrid control to embed a DataGrid control inside another DataGrid control to create, so called, MasterDetail view of your data.

You can bind your data to following kind of columns.

  • BoundColumn
  • ButtonColumn
  • EditCommandColumn
  • HyperLinkColumn
  • TemplateColumn

The first four column types provide a predefined kind of output which is prety much self explanatory from their names. It is the fifth type, TemplateColumn which provides the place holder for embedding any type of controls inside the DataGrid. We will use this column to embed our outer DataGrid. The example we have shown in this article display regional monthly sales of company in the embeded DataGrid inside the anual sales DataGrid.

<asp:DataGrid ID="RagionalSales_Grid" Runat="server" DataSource="<%# m_dsRegionalSalesMain %>"
 AutoGenerateColumns="False" PageSize="1" AllowPaging="True" CellPadding="4"
 BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px" BackColor="White">
 <SelectedItemStyle Font-Bold="True" ForeColor="#663399" BackColor="#FFCC66"></SelectedItemStyle>
 <AlternatingItemStyle Font-Bold="True" ForeColor="Maroon" BackColor="White"></AlternatingItemStyle>
 <ItemStyle Font-Bold="True" ForeColor="#330099" BackColor="White"></ItemStyle>
 <HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
 <FooterStyle ForeColor="#330099" BackColor="#FFFFCC"></FooterStyle>
 <Columns>
 	<asp:BoundColumn DataField="RegionName" SortExpression="RegionName" HeaderText="Region Name">>
 	</asp:BoundColumn>
	<asp:BoundColumn DataField="SaleYear" SortExpression="SaleYear" HeaderText="Year">
	</asp:BoundColumn>
	<asp:TemplateColumn HeaderText="Monthly Sales">
		<ItemTemplate>
			<asp:DataGrid ID="MonthlySales_Grid" Runat="server" AllowPaging="False"
			AllowSorting="False" AutoGenerateColumns="False"
			ShowHeader="False" BorderColor="#DEBA84" CellPadding="3" CellSpacing="2"
			 BorderStyle="None" BackColor="#DEBA84" BorderWidth="1px">
				<ItemStyle ForeColor="#8C4510" BackColor="#FFF7E7"></ItemStyle>
				<Columns>
					<asp:BoundColumn DataField="SaleMonth"></asp:BoundColumn>
					<asp:BoundColumn DataField="TotalSale" DataFormatString="{0:c2}">
					</asp:BoundColumn>
				</Columns>
			</asp:DataGrid>
		</ItemTemplate>
	</asp:TemplateColumn>
 </Columns>
<PagerStyle HorizontalAlign="Center" ForeColor="#330099" BackColor="#FFFFCC" Mode="NumericPages">
</PagerStyle>
</asp:DataGrid>						
						

There is only one tiny problem here. When you embed a DataGrid inside TemplateColumn, you don't get the ability to use the control wizard to format the inside grid. But you can always create the inner grid separately, format it and then paste it inside the TemplateColumn.

How to bind inner DataGrid to data source?

This is where things get really interesting. The inside grid or also called the details grid needs a data source for every row of the master grid. Therefore we need some mechanism such that we can get the details data based on some key values in the row of the master grid. We can't bind the inside grid to one data set. So how do we do it. The folowing code shows you the use of ItemBound event of the Master Data Grid to get the data for details grid and bind it to the control. The one very important thing that code demonstrates is that how can you add event handlers for the inner grid. The problem is that inside DataGrid object does not get created before the outside grid. Therefore you can't add the event handlers at the design view. If you try to do it, the code will throw run time exception that the object refrence does not exist for inner DataGrid.

private void OnMainGridDataBound(object sender, DataGridItemEventArgs e)
{
	if (e.Item.ItemType == ListItemType.AlternatingItem ||
		e.Item.ItemType == ListItemType.Item)
	{
		// Get data for that year and region and create data set 
		Control obCtl = e.Item.FindControl("MonthlySales_Grid");
		if (null != obCtl && obCtl is DataGrid)
		{
			// Bind this grid to monthly sales data..
			DataRowView drv = (DataRowView)e.Item.DataItem;
			int iRegionID = Convert.ToInt32(drv["Region_id"]);
			int iYear = Convert.ToInt32(drv["SaleYear"]);
			DataSet ds = this.GetMonthlySalesData(iRegionID, iYear);
			DataGrid dg = (DataGrid)obCtl;
			dg.ItemDataBound += 
			 new DataGridItemEventHandler(this.OnMonthlySalesGridDataBound);
			dg.DataSource = ds;
			dg.DataBind();
		}
	}
}

private void OnMonthlySalesGridDataBound(object sender, DataGridItemEventArgs e)
{
	if (e.Item.ItemType == ListItemType.AlternatingItem ||
		e.Item.ItemType == ListItemType.Item)
	{
		// Get the value for first column representing month.
		int iMonth = Convert.ToInt32(e.Item.Cells[0].Text);
		e.Item.Cells[0].Text = this.GetMonth(iMonth);
	}
}
						
Go Freelance
Home     About us     Contact us    Copyright    Privacy Policy    Return Policy    Advertisers
Copyright © Netomatix