Ref:
http://aspsnippets.com/Articles/ASPNet-Nested-GridViews-GridView-inside-GridView-with-Expand-and-Collapse-feature.aspx
This way:
HTML:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
body
{
font-family: Arial;
font-size: 10pt;
}
.Grid td
{
background-color: #A1DCF2;
color: black;
font-size: 10pt;
line-height: 200%;
}
.Grid th
{
background-color: #3AC0F2;
color: White;
font-size: 10pt;
line-height: 200%;
}
.ChildGrid td
{
background-color: #eee !important;
color: black;
font-size: 10pt;
line-height: 200%;
}
.ChildGrid th
{
background-color: #6C6C6C !important;
color: White;
font-size: 10pt;
line-height: 200%;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$("[src*=plus]").live("click", function () {
$(this).closest("tr").after("<tr><td></td><td colspan = '999'>" + $(this).next().html() + "</td></tr>")
$(this).attr("src", "images/minus.png");
});
$("[src*=minus]").live("click", function () {
$(this).attr("src", "images/plus.png");
$(this).closest("tr").next().remove();
});
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:GridView ID="gvDepartments" runat="server" AutoGenerateColumns="false" CssClass="Grid"
DataKeyNames="Dept_Id" OnRowDataBound="OnRowDataBound">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<img alt="" style="cursor: pointer" src="images/plus.png" />
<asp:Panel ID="pnlEmployees" runat="server" Style="display: none">
<asp:GridView ID="gvEmployees" runat="server" AutoGenerateColumns="false" DataKeyNames="Id"
OnRowDeleting="gvEmployees_OnRowDeleting" OnRowUpdating="UpdateCustomer" OnRowEditing="gvEmployees_OnRowEditing"
CssClass="ChildGrid">
<Columns>
<asp:TemplateField HeaderText="DepartmentId" Visible="false">
<ItemTemplate>
<asp:Label ID="lblDepartmentId" Text='<%# Eval("DepartmentId") %>' runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Id">
<ItemTemplate>
<asp:Label ID="lblId" Text='<%# Eval("Id") %>' runat="server"></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField ItemStyle-Width="100px" HeaderText="Name">
<ItemTemplate>
<asp:Label ID="lblName" runat="server" Text='<%# Eval("Name")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtName" runat="server" Text='<%# Bind("Name")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField ItemStyle-Width="100px" HeaderText="Address">
<ItemTemplate>
<asp:Label ID="lblAddress" runat="server" Text='<%# Eval("Address")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:TextBox ID="txtAddress" runat="server" Text='<%# Bind("Address")%>'></asp:TextBox>
</EditItemTemplate>
</asp:TemplateField>
<asp:ButtonField CommandName="Edit" Text="Edit" />
<asp:ButtonField CommandName="Delete" Text="Delete" />
<asp:ButtonField CommandName="Update" Text="Update" />
</Columns>
</asp:GridView>
</asp:Panel>
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField ItemStyle-Width="150px" DataField="Dept_Id" HeaderText="Dept Id" />
<asp:BoundField ItemStyle-Width="150px" DataField="Dept_Name" HeaderText="Dept Name" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
C#:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
gvDepartments.DataSource = GetData("select top 10 * from Departments");
gvDepartments.DataBind();
}
}
private static DataTable GetData(string query)
{
string strConnString = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
using (SqlConnection con = new SqlConnection(strConnString))
{
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;
}
}
}
}
}
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
string DepartmentId = gvDepartments.DataKeys[e.Row.RowIndex].Value.ToString();
GridView gvEmployees = e.Row.FindControl("gvEmployees") as GridView;
gvEmployees.DataSource = GetData(string.Format("select top 3 Id,Name,Address,DepartmentId from Employees where DepartmentId='{0}'", DepartmentId));
gvEmployees.DataBind();
}
}
protected void gvEmployees_OnRowEditing(object sender, GridViewEditEventArgs e)
{
GridView gvEmployees = sender as GridView;
GridViewRow row = gvEmployees.Rows[e.NewEditIndex];
int DepartmentId = Convert.ToInt32((row.Cells[0].FindControl("lblDepartmentId") as Label).Text);
gvEmployees.EditIndex = e.NewEditIndex;
gvEmployees.DataSource = GetData(string.Format("select top 3 Id,Name,Address,DepartmentId from Employees where DepartmentId='{0}'", DepartmentId));
gvEmployees.DataBind();
}
protected void gvEmployees_OnRowDeleting(object sender, GridViewDeleteEventArgs e)
{
GridView gvEmployees = sender as GridView;
int Id = Convert.ToInt32(gvEmployees.DataKeys[e.RowIndex].Value);
this.Delete(Id);
gvEmployees.EditIndex = -1;
Response.Redirect("CS.aspx");
}
private void Delete(int id)
{
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
string sqlStatment = "DELETE FROM Employees WHERE Id = @id";
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(sqlStatment, con))
{
con.Open();
cmd.Parameters.AddWithValue("@Id", id);
cmd.ExecuteNonQuery();
con.Close();
}
}
}
protected void UpdateCustomer(object sender, GridViewUpdateEventArgs e)
{
GridView gvEmployees = sender as GridView;
int id = Convert.ToInt32(((Label)gvEmployees.Rows[e.RowIndex].FindControl("lblId")).Text);
string name = ((TextBox)gvEmployees.Rows[e.RowIndex].FindControl("txtName")).Text;
string address = ((TextBox)gvEmployees.Rows[e.RowIndex].FindControl("txtAddress")).Text;
int index = name.IndexOf(",");
string finalName = name.Substring(index + 1);
index = address.IndexOf(",");
string finalAddress = address.Substring(index + 1);
index = address.IndexOf(",");
this.Update(id, finalName, finalAddress);
gvEmployees.EditIndex = -1;
gvDepartments.DataSource = GetData("select top 10 * from Departments");
gvDepartments.DataBind();
}
private void Update(int id, string name, string address)
{
string constr = ConfigurationManager.ConnectionStrings["constr"].ConnectionString;
string sqlStatment = "UPDATE Employees SET Name = @Name,Address = @Address WHERE Id = @id";
using (SqlConnection con = new SqlConnection(constr))
{
using (SqlCommand cmd = new SqlCommand(sqlStatment, con))
{
con.Open();
cmd.Parameters.AddWithValue("@Id", id);
cmd.Parameters.AddWithValue("@Name", name);
cmd.Parameters.AddWithValue("@Address", address);
cmd.ExecuteNonQuery();
con.Close();
}
}
}
Namespace:
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
Sql:
CREATE TABLE [dbo].[Departments](
[Dept_Id] [int] IDENTITY(1,1) NOT NULL,
[Dept_Name] [varchar](50) NOT NULL,
CONSTRAINT [PK_Departments] PRIMARY KEY CLUSTERED
(
[Dept_Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE TABLE [dbo].[Employees](
[Id] [int] NOT NULL,
[Name] [varchar](50) NOT NULL,
[Address] [varchar](100) NOT NULL,
[DepartmentId] [int] NULL,
CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Image:
When You click on Edit Button Child GridView will be sone you have to click on Plus sign once again. This time you will be able to see the TextBox edit the TextBox value. On Update Button i am removing the text from 0 to fisrt index of ,(comma). This is because of Child GridView is getting bind two times. After that i am populating all once again.
Thank You.