Simple Nested Gridview In ASP.NET

2011-05-14

Here is the code for creating Nested gridview in asp.net, one can do this easily in asp.net. I have seen third party controls like Infragistics & DevExpress control kit where they provide this feature in their grid controls. Although we cannot compare this grid with thiers, but this one is sufficient for a normal user scenario requirements
Example of Buisness Requirement where Nested GridView should be displayed:
In Estimation area there is a requirement of knowing the rates of all the contractors for a given material , then it would be good if our grid can show like as in given below figures.


HTML Code
-------------
<table style="width:100%;height:100%;">

<tr>

<td>

<asp:GridView ID="grdOuterGridView" runat="server" AllowPaging="True"

AutoGenerateColumns="False" DataKeyNames="MaterialID"

onrowdatabound="grdOuterGridView_RowDataBound" CellPadding="4"

ForeColor="#333333" GridLines="None">

<AlternatingRowStyle BackColor="White" />

<Columns>

<asp:TemplateField>

<ItemTemplate>

<a href="javascript:switchViews('div<%# Eval("MaterialID") %>');">

<img id="imgdiv<%# Eval("MaterialID") %>" title="Click to show/hide orders" border="0" src="images/rightarrow.png" width="15px" />

</a>

</ItemTemplate>

</asp:TemplateField>



<asp:BoundField HeaderText="Material" DataField="Material" />

<asp:BoundField HeaderText="Code" DataField="MaterialCode"/>

<asp:TemplateField>

<ItemTemplate>

</td></tr>

<tr>

<td colspan="100%">

<div id="div<%# Eval("MaterialID") %>" style="display:none;position:relative;left:25px;" >

<asp:GridView ID="grdInnerGridView" runat="server" Width="80%"

AutoGenerateColumns="false" DataKeyNames="RateID"

EmptyDataText="No rates available from the contractors." >

<Columns>

<asp:BoundField HeaderText="Contractor Name" DataField="ContractorName" />

<asp:BoundField HeaderText="Rate" DataField="Rate" />





</Columns>

</asp:GridView>

</div>

</td>

</tr>



</ItemTemplate>



</asp:TemplateField>

</Columns>

<EditRowStyle BackColor="#2461BF" />

<FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

<PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />

<RowStyle BackColor="#EFF3FB" />

<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />

<SortedAscendingCellStyle BackColor="#F5F7FB" />

<SortedAscendingHeaderStyle BackColor="#6D95E1" />

<SortedDescendingCellStyle BackColor="#E9EBEF" />

<SortedDescendingHeaderStyle BackColor="#4870BE" />

</asp:GridView>

</td>

</tr>

</table>














C# Code
------------
using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Data.SqlClient;

using System.Data;



namespace MinimizeMaximizeTab

{

public partial class NestedGridview : System.Web.UI.Page

{

SqlConnection objConnection = new SqlConnection("Integrated security=false;user id='sa';pwd='beta';database='ASIF_DB'");

SqlCommand objCommand = new SqlCommand();



protected void Page_Load(object sender, EventArgs e)

{

objCommand.Connection = objConnection;

FillOuterGrid();

}



protected void grdOuterGridView_RowDataBound(object sender, GridViewRowEventArgs e)

{

if (e.Row.RowType == DataControlRowType.DataRow)

{

int materialID = (int)grdOuterGridView.DataKeys[e.Row.RowIndex].Values["MaterialID"];

GridView innerGridView = (GridView)e.Row.FindControl("grdInnerGridView");

FillInnerGrid(materialID, innerGridView);

}



}



private void FillOuterGrid()

{

objCommand.CommandText = "SELECT MaterialID,Material,MaterialCode FROM Materials";

SqlDataAdapter objAdap = new SqlDataAdapter(objCommand);

DataTable dtMaterials=new DataTable();

objConnection.Open();

objAdap.Fill(dtMaterials);

objConnection.Close();

grdOuterGridView.DataSource = dtMaterials;

grdOuterGridView.DataBind();

}



private void FillInnerGrid(int materialID, GridView grdInnerGridView)

{

objCommand.CommandText = "SELECT RateID,ContractorName,Rate from Contractors INNER JOIN ContractorRates on Contractors.ContractorID = ContractorRates.ContractorID where MaterialID="+ materialID;

SqlDataAdapter objAdap = new SqlDataAdapter(objCommand);

DataTable dtContractorRates = new DataTable();

objConnection.Open();

objAdap.Fill(dtContractorRates);

objConnection.Close();

grdInnerGridView.DataSource = dtContractorRates;

grdInnerGridView.DataBind();

}





}

}




Javascript Code

---------------------



function switchViews(obj)

{

var div = document.getElementById(obj);

var img = document.getElementById('img' + obj);



if (div.style.display=="none")

{

div.style.display = "inline";

img.src="images/downarrow.png" ;

img.title = "Close to view other materials";

}

else

{

div.style.display = "none";

img.src="images/rightarrow.png" ;

img.title = "Expand to view other contracto rates";

}

}
Summary -------- 1. Create a template & place a gridview in it 2. Fill the gridview at the row databound of parent gridview 3. Create a tag a to call javascript function which passes the id of the div tag inside which inner gridview is placed at the first template column of parent grid. 4. On calling javascript function change the display from inline/block to none or none to inline/block & also change the image too

2 comments:

Bryan and Christina said...

This is exactly what I was thinking of implementing for a small address book app. Cheers, thanks.

Bryan

gcastro said...

This is Exactly what i was looking for, excelent! thanks