Friday, June 19, 2015

Edit a nested or inner Grid and Show inner grid on expand/collapse on outer Grid



Introduction:
In my previous article, I explained Change dropdownlist value on selection of another dropdownlist in gridview. This article will describe Edit a nested or inner Grid and Show inner grid on expand/collapse on outer Grid.
Sometimes you need two dropdownlist in gridview and one must be rebind on selection of another.i.e. Employee-Department,State-City, Subject-faculty etc.
Description:
As we all know GridView is used to show data in tabular format. This comes with many inbuilt features.
In this article, I will explain how we use a grid inside another grid. I will also explain how we can edit inner grid content. I hope this article will help you to understand the functionalities and event bubbling of inner grid.
Before you continue, first of all we will create two tables, tblState and tblCity, in database and fill some data into respective tables as shown below.
State_Id
StateName

City_Id
City_name
State_id
1
Andhra Pradesh

1
Hyderabad
1
2
Assam

2
Tirupati
1
3
Bihar

3
Visakhapatnam
1
4
Chhattisgarh

4
Dispur
2
5
Goa

5
Patna
3
6
Gujarat

6
Nalanda
3
7
Haryana

7
Raipur
4
8
Himachal Pradesh

8
Panaji
5



9
Ahmedabad
6




Now write code in your aspx page as shown below.

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="ExpandablegridinC.aspx.cs" Inherits="ExpandablegridinC" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Grid inside grid and show inner grid on expand on click of outer grid</title>

    <script language="javascript" type="text/javascript">
        function divexpandcollapse(divname) {
            var div = document.getElementById(divname);
            var spn = document.getElementById('sp' + divname);

            if (div.style.display == "none") {
                div.style.display = "table-row";
                spn.innerText = "Hide";
            } else {
                div.style.display = "none";
                spn.innerText = "Show";
            }
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <table width="100%" cellpadding="0" cellspacing="0" border="0">
        <tr>
            <td align="center">
                <asp:GridView ID="gvState" AutoGenerateColumns="false" RowStyle-Height="28px" OnRowDataBound="gvState_RowDataBound"
                    Width="35%" runat="server" BackColor="#ececec">
                    <HeaderStyle BackColor="#3a4078" ForeColor="#FFFFFF" Font-Bold="True" />
                    <AlternatingRowStyle BackColor="white" />
                    <Columns>
                        <asp:TemplateField ShowHeader="true" HeaderText="#">
                            <HeaderStyle Font-Underline="false" HorizontalAlign="center" Width="1%" />
                            <ItemStyle HorizontalAlign="center" />
                            <ItemTemplate>
                                <%# Container.DataItemIndex + 1%>.
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField ShowHeader="true" HeaderText="State" SortExpression="State_Name">
                            <HeaderStyle Font-Underline="false" HorizontalAlign="center" Width="4%" />
                            <ItemStyle HorizontalAlign="Left" />
                            <ItemTemplate>
                                <%# DataBinder.Eval(Container.DataItem, "StateName")%>
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField ShowHeader="true" HeaderText="Show City">
                            <HeaderStyle Font-Underline="false" HorizontalAlign="center" Width="3%" />
                            <ItemStyle HorizontalAlign="Center" />
                            <ItemTemplate>
                                <a href="JavaScript:divexpandcollapse('div<%# Eval("State_Id") %>_State');">
                                    <span id="spdiv<%# Eval("State_Id") %>_State">Show</span>
                                    <asp:Label ID="lblStateId" Text='<%#DataBinder.Eval(Container.DataItem, "State_Id")%>'
                                        Visible="false" runat="server"></asp:Label>
                                    <tr id="div<%# Eval("State_Id") %>_State" style="position: inherit; display: none;
                                        overflow: auto">
                                        <td colspan="12" style="text-align: left !important; padding-left: 20px; padding-top: 5px;
                                            padding-bottom: 10px; background-color: #4A4A4A;">
                                            <asp:GridView ID="gvCity" runat="Server" AutoGenerateColumns="false" AutoGenerateEditButton="false"
                                                Width="98%" RowStyle-Height="18px" BackColor="#ececec" OnRowCancelingEdit="gvCity_RowCancelingEdit"
                                                OnRowEditing="gvCity_RowEditing" OnRowUpdating="gvCity_RowUpdating">
                                                <HeaderStyle BackColor="#3a4078" ForeColor="#FFFFFF" Font-Bold="True" />
                                                <AlternatingRowStyle BackColor="white" />
                                                <EditRowStyle BackColor="lightblue" />
                                                <Columns>
                                                    <asp:TemplateField ShowHeader="true" HeaderText="#">
                                                        <HeaderStyle Font-Underline="false" HorizontalAlign="center" Width="1%" />
                                                        <ItemStyle HorizontalAlign="center" />
                                                        <ItemTemplate>
                                                            <%# Container.DataItemIndex + 1%>.
                                                        </ItemTemplate>
                                                    </asp:TemplateField>
                                                    <asp:TemplateField ShowHeader="true" HeaderText="Name">
                                                        <HeaderStyle Font-Underline="false" HorizontalAlign="Center" Width="5%" />
                                                        <ItemStyle HorizontalAlign="Left" />
                                                        <EditItemTemplate>
                                                            <asp:TextBox ID="txtCityName" Width="150" MaxLength="100" runat="server" Text='<%# Bind("City_Name") %>'
                                                                ValidationGroup="EditRecord"></asp:TextBox>
                                                        </EditItemTemplate>
                                                        <ItemTemplate>
                                                            <asp:Label ID="lblCityName" Text='<%# DataBinder.Eval(Container.DataItem, "City_Name")%>'
                                                                runat="server"></asp:Label>
                                                        </ItemTemplate>
                                                    </asp:TemplateField>
                                                    <asp:TemplateField ShowHeader="true" HeaderText="Functions">
                                                        <HeaderStyle Font-Underline="false" HorizontalAlign="Center" Width="2%" />
                                                        <EditItemTemplate>
                                                            <asp:LinkButton ID="lnkUpdate" CommandName="Update" Text="Update" runat="server"></asp:LinkButton>
                                                            <asp:LinkButton ID="lnkCancel" runat="server" CommandName="Cancel" Text="Cancel"></asp:LinkButton>
                                                            <asp:Label ID="lblCityId" Text='<%# DataBinder.Eval(Container.DataItem, "City_Id")%>'
                                                                Visible="false" runat="server"></asp:Label>
                                                        </EditItemTemplate>
                                                        <ItemTemplate>
                                                            <asp:Label ID="lblEditCityId" Text='<%# DataBinder.Eval(Container.DataItem, "City_Id")%>'
                                                                Visible="false" runat="server"></asp:Label>
                                                            <asp:LinkButton ID="lnkEdit" CommandName="Edit" Text="Edit" runat="server"></asp:LinkButton>
                                                        </ItemTemplate>
                                                    </asp:TemplateField>
                                                </Columns>
                                            </asp:GridView>
                                        </td>
                                    </tr>
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </td>
        </tr>
    </table>
    </form>
</body>
</html>

Once you finish your aspxpage design, let’s complete code behind.
Add Following namespace in your cs page.
C# Code:
using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using System.Data.SqlClient;

First of all we bind parent gridview and after then we will use its three events i.e. RowDataBound, RowCancelingEdit, RowEditing of childgrid .

public partial class ExpandablegridinC : System.Web.UI.Page
{
    static DataSet dsTemp;
    string gvUniqueID = String.Empty;
    int gvEditIndex = -1;
    string strCon = @"Data Source=TempDB;Initial Catalog=temp;User ID=user; Password=dbPass;";
   
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!Page.IsPostBack)
            GetStateWithCity();
    }

    ///<summary>
    /// This fuction is used to bind gridview
    ///</summary>
    private void GetStateWithCity()
    {
        dsTemp = new DataSet();
        using (SqlConnection con = new SqlConnection(strCon))
        {
            con.Open();
            SqlCommand cmd = new SqlCommand("SELECT S.State_Id, S.StateName,C.City_Id,C.City_Name FROM tbl_City C INNER JOIN tbl_State S on C.State_Id = S.State_Id;SELECT State_id,Statename FROM tbl_State;", con);
            SqlDataAdapter da = new SqlDataAdapter(cmd);
            DataTable dt = new DataTable();
            da.Fill(dsTemp);

            if (dsTemp.Tables != null)
            {
                gvState.DataSource = dsTemp.Tables[1];
                gvState.DataBind();
            }
        }
    }

    /// <summary>
    /// This is rowdatabound event of gridview that binds inner gridview of every row
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void gvState_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        if (e.Row.RowType == DataControlRowType.DataRow)
        {
            try
            {
                Label lblStateId = (Label)e.Row.FindControl("lblStateId");
                GridView gvCity = (GridView)e.Row.FindControl("gvCity");
                if (gvCity.UniqueID == gvUniqueID)
                {
                    gvCity.EditIndex = gvEditIndex;
                    ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "Expand", "<SCRIPT LANGUAGE='javascript'>divexpandcollapse('div" + lblStateId.Text.Trim() + "_State');</script>", false);
                }
                DataRow[] drDataRow = null;
                if (dsTemp.Tables[0] != null)
                    drDataRow = dsTemp.Tables[0].Select("State_Id = " + lblStateId.Text.Trim());

                DataTable dtBind = new DataTable();
                dtBind = drDataRow.CopyToDataTable();
                gvCity.DataSource = dtBind;
                gvCity.DataBind();
            }
            catch (Exception ex)
            {
            }
        }
    }

    /// <summary>
    /// This event will occur when the Cancel button of a row in edit mode is clicked, but before the row exits edit mode.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void gvCity_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        GridView gvCity = (GridView)sender;
        gvUniqueID = gvCity.UniqueID;
        gvEditIndex = -1;
        GetStateWithCity();
    }

    /// <summary>
    /// This event will occur when the Update button of a row in edit mode is clicked.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void gvCity_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        GridView gvCity = (GridView)sender;
        gvUniqueID = gvCity.UniqueID;

        Label lblCityId = (Label)gvCity.Rows[e.RowIndex].FindControl("lblCityId");
        TextBox txtCityName = (TextBox)gvCity.Rows[e.RowIndex].FindControl("txtCityName");
        using (SqlConnection con = new SqlConnection(strCon))
        {
            con.Open();
            SqlCommand cmd = new SqlCommand("Update tbl_City set City_Name = '" + txtCityName.Text + "' Where City_Id = " + lblCityId.Text, con);
            cmd.ExecuteNonQuery();
        }
        GetStateWithCity();
    }

    /// <summary>
    /// This vent will occur when a row's Edit button is clicked, but before the GridView control enters edit mode.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void gvCity_RowEditing(object sender, GridViewEditEventArgs e)
    {
        GridView gvCity = (GridView)sender;
        gvUniqueID = gvCity.UniqueID;
        gvEditIndex = e.NewEditIndex;
        GetStateWithCity();
    }
}

VB.NET Code:
Imports System
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data
Imports System.Data.SqlClient

We will write same code in vb script.
Partial Class ExpandablegridinVB
    Inherits System.Web.UI.Page

    Dim dsTemp As DataSet
    Private gvUniqueID As String = String.Empty
    Private gvEditIndex As Integer = -1
    Private strCon As String = @"Data Source=TempDB;Initial Catalog=temp;User ID=user; Password=dbPass;"

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
        If Not Page.IsPostBack Then
            GetStateWithCity()
        End If
    End Sub

    Private Sub GetStateWithCity()
        dsTemp = New DataSet()
        Using con As New SqlConnection(strCon)
            con.Open()
            Dim cmd As New SqlCommand("SELECT S.State_Id, S.StateName, C.City_Id, C.City_Name FROM tbl_City C INNER JOIN tbl_State S on C.State_Id = S.State_Id; SELECT State_id, Statename FROM tbl_State;", con)
            Dim da As New SqlDataAdapter(cmd)
            Dim dt As New DataTable()
            da.Fill(dsTemp)
            gvState.DataSource = dsTemp.Tables(1)
            gvState.DataBind()
        End Using
    End Sub

    Protected Sub gvState_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
        If e.Row.RowType = DataControlRowType.DataRow Then
            Dim lblStateId = DirectCast(e.Row.FindControl("lblStateId"), Label)
            Dim gvCity = DirectCast(e.Row.FindControl("gvCity"), GridView)

            If gvCity.UniqueID = gvUniqueID Then
                gvCity.EditIndex = gvEditIndex
                ScriptManager.RegisterStartupScript(Me, GetType(Page), "Expand", "<SCRIPT LANGUAGE='javascript'>divexpandcollapse('div" + lblStateId.Text.Trim() + "_State');</script>", False)
            End If

            Dim drDataRow As DataRow()
            drDataRow = dsTemp.Tables(0).Select("State_Id = " + lblStateId.Text.Trim())

            Dim dtBind As New DataTable
            dtBind = drDataRow.CopyToDataTable()
            gvCity.DataSource = dtBind
            gvCity.DataBind()
        End If
    End Sub

    Protected Sub gvCity_RowCancelingEdit(ByVal sender As Object, ByVal e As GridViewCancelEditEventArgs)
        Dim gvCity = DirectCast(sender, GridView)
        gvUniqueID = gvCity.UniqueID
        gvEditIndex = -1
        GetStateWithCity()
    End Sub

    Protected Sub gvCity_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs)
        Dim gvCity = DirectCast(sender, GridView)
        gvUniqueID = gvCity.UniqueID
        Dim lblCityId = DirectCast(gvCity.Rows(e.RowIndex).FindControl("lblCityId"), Label)
        Dim txtCityName = DirectCast(gvCity.Rows(e.RowIndex).FindControl("txtCityName"), TextBox)

        Using con As New SqlConnection(strCon)
            con.Open()
            Dim cmd As New SqlCommand("Update tbl_City set City_Name = '" + txtCityName.Text + "' Where City_Id = " + lblCityId.Text, con)
            cmd.ExecuteNonQuery()
            GetStateWithCity()
        End Using
    End Sub

    Protected Sub gvCity_RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
        Dim gvCity = DirectCast(sender, GridView)
        gvUniqueID = gvCity.UniqueID
        gvEditIndex = e.NewEditIndex
        GetStateWithCity()
    End Sub

End Class

Demo:





No comments: