Nested GridView and Crud Operation
Working on single GridView with all CRUD operations is a tedious task to implement but not difficult.
If we need to implement in nested form then it makes it more complex compared to single GridView. In the below case, I have implemented a nested GridView where the following provision is made available.
- Enter new row/ record using footer of a template in outer as well as inner GridView.
- Edit, Update, Delete record/rows of particular GridView.
- Collapsible inner GridView for every row of an outer GridView i.e subset of every record.
Design Outer GridView
- <asp:GridView ID="grdParent" AutoGenerateColumns="false" ShowFooter="true" EmptyDataText="No Records Found" CssClass="table table-bordered" runat="server" OnRowDataBound="grdParent_RowDataBound" OnRowCancelingEdit="grdParent_RowCancelingEdit" OnRowCommand="grdParent_RowCommand" OnRowEditing="grdParent_RowEditing" OnRowUpdating="grdParent_RowUpdating">
- <Columns>
- <asp:TemplateField HeaderText="Name">
- <ItemTemplate>
- <asp:Label ID="lblName" runat="server" Text='<%# Eval("Name")%>' /> </ItemTemplate>
- <EditItemTemplate>
- <asp:TextBox ID="txtEditName" runat="server" placeholder="Enter Name Please" Text='<%# Eval("Name")%>' /> </EditItemTemplate>
- <FooterTemplate>
- <asp:TextBox ID="txtName" runat="server" placeholder="Enter Name Please" /> </FooterTemplate>
- </asp:TemplateField>
- <asp:TemplateField HeaderText="Action">
- <ItemTemplate>
- <asp:LinkButton runat="server" ID="btnEdit" CommandName="Edit" ToolTip="Edit" Text="Edit" CssClass=""><i class="fa fa-x fa-edit"></i></asp:LinkButton>
- <asp:LinkButton runat="server" ID="btndelete" ToolTip="Remove" CommandName="DeleteParentRow" Text="Delete" CssClass=""><span class="fa fa-x fa-close"></span></asp:LinkButton>
- </ItemTemplate>
- <EditItemTemplate>
- <asp:LinkButton runat="server" ID="btnSubUpdate" CommandName="Update" ToolTip="Update" Text="Update" CssClass=""><i class="fa fa-x fa-thumbs-up"></i></asp:LinkButton>
- <asp:LinkButton runat="server" ID="btnCancel" ToolTip="Cancel" CommandName="Cancel" Text="Cancel" CssClass=""><i class="fa fa-x fa-thumbs-down"></i></asp:LinkButton>
- </EditItemTemplate>
- <FooterTemplate>
- <asp:Button ID="btnSubAdd" CommandName="AddNew" runat="server" Text="Add New Record" CssClass="btn btn-sm btn-primary" /> </FooterTemplate>
- </asp:TemplateField>
- </Columns>
- </asp:GridView>
Simple Design for outer GridView where fields are bound within column tag using item template.
Edit template is used for editing and updating rows.
FooterTemplate is used as a provision to enter a new record to grid at the bottom of the GridView.
We need to mention footer template to every field of a row where there is a need to enter a new value.
Design Inner GridView
Add one more item template at the end of parent GridView which will replicate or generate a child GridView for every bound row of parent grid.
- <asp:TemplateField>
- <ItemTemplate>
- <tr>
- <td>
- <asp:GridView ID="gvChildGrid" CssClass="table table-bordered" ShowFooter="true" runat="server" AutoGenerateColumns="false" OnRowDataBound="gvChildGrid_RowDataBound" OnRowEditing="gvChildGrid_RowEditing" OnRowCancelingEdit="gvChildGrid_RowCancelingEdit" OnRowCommand="gvChildGrid_RowCommand" OnRowUpdating="gvChildGrid_RowUpdating">
- <Columns>
- <asp:TemplateField HeaderText="Name">
- <ItemTemplate>
- <asp:Label ID="lblSubName" runat="server" Text='<%# Eval("SubName")%>' /> </ItemTemplate>
- <EditItemTemplate>
- <asp:TextBox ID="txtSubEditName" runat="server" placeholder="Enter child Name Please" Text='<%# Eval("SubName")%>' /> </EditItemTemplate>
- <FooterTemplate>
- <asp:TextBox ID="txtSubName" runat="server" placeholder="Enter child Name Please" /> </FooterTemplate>
- </asp:TemplateField>
- <asp:TemplateField HeaderText="Action">
- <ItemTemplate>
- <asp:LinkButton runat="server" ID="btnChildEdit" CommandName="Edit" ToolTip="Edit" Text="Edit" CssClass=""><i class="fa fa-x fa-edit"></i></asp:LinkButton>
- <asp:LinkButton runat="server" ID="btnChilddelete" ToolTip="Remove" CommandName="DeleteParentRow" Text="Delete" CssClass=""><span class="fa fa-x fa-close"></span></asp:LinkButton>
- </ItemTemplate>
- <EditItemTemplate>
- <asp:LinkButton runat="server" ID="btnChildUpdate" CommandName="Update" ToolTip="Update" Text="Update" CssClass=""><i class="fa fa-x fa-thumbs-up"></i></asp:LinkButton>
- <asp:LinkButton runat="server" ID="btnChildCancel" ToolTip="Cancel" CommandName="Cancel" Text="Cancel" CssClass=""><i class="fa fa-x fa-thumbs-down"></i></asp:LinkButton>
- </EditItemTemplate>
- <FooterTemplate>
- <asp:Button ID="btnChildAdd" CommandName="AddNew" runat="server" Text="Add New Record" CssClass="btn btn-sm btn-primary" /> </FooterTemplate>
- </asp:TemplateField>
- </Columns>
- <td>
- </tr>
- </ItemTemplate>
- </asp:TemplateField>
This inner GridView will function with CRUD operations the same as outer GridView but it has the challenge to identify which inner GridView has been called for functionality.
Functionality for Parent Gridview
- Protected void grdParent_RowDataBound: Columns get bind as per data source.
- Protected void grdParent_RowCommand: Based on CommandName, a respective set of operation execute like AddNew Row, Delete Row.
- Protected void grdParent_RowEditing: Edit particular rowindex of a GridView.
- Protected void grdParent_RowUpdating: Execute Edit functionality for selected editing row.
- Protected void grdParent_RowCancelingEdit: Cancel Edit functionality for any row.
Bind internal Grid in Parent RowdataBound event.
Code Snippet
- if (e.Row.RowType == DataControlRowType.DataRow)
- {
- GridView gv = (GridView) e.Row.FindControl("gvChildGrid");
- Find gridview
- for every Row
- DataTable dtAction = new DataTable();
- dtAction = LoadSubCORList(Convert.ToString(id));
- if (dtAction.Row.Count > 0) {
- gv.DataSource = dtAction
- gv.DataBind();
- } else {
-
- dtAction.Rows.Add(dtAction.NewRow());
- gv.DataSource = dtAction;
- gv.DataBind();
- int columncount = gv.Rows[0].Cells.Count;
- gv.Rows[0].Cells.Clear();
- gv.Rows[0].Cells.Add(new TableCell());
- gv.Rows[0].Cells[0].ColumnSpan = columncount;
- gv.Rows[0].Cells[0].Text = "No Records Found";
- }
- }
Functionality for Child Gridview
- protected void gvChildGrid_RowCommand : Based on CommandName, respective Set of operation execute like AddNew Row, Delete Row on particular inner grid.
- protected void gvChildGrid_RowDataBound :Columns get bind as per datasource
- protected void gvChildGrid_RowEditing: Edit particular rowindex of inner gridview
- protected void gvChildGrid_RowCancelingEdit: Cancel Edit functionality for any row.
- protected void gvChildGrid_RowUpdating : Execute Edit functionality for selected editing row.
In the above case, it's difficult to figure out which inner GridView is functioning at a time.
The following code was used in Child GridView events to identify the functioning GridView.
Code Snippets
- GridView GV = (GridView)sender;
- GridViewRow grdParent = (GridViewRow)GridView2.Parent.Parent;
Use the above line to identify the inner grid view to perform selective operations on respective inner grid.
Script For Collapsible Events
- <script language="javascript" type="text/javascript">
- function divexpandcollapse(divname) {
- var div = document.getElementById(divname);
- var img = document.getElementById('img' + divname);
- if (div.style.display == "none") {
- div.style.display = "inline";
- img.src = "../images/minus.png";
- } else {
- div.style.display = "none";
- img.src = "../images/plus.png";
- }
- }
- </script>
Add the following itemtemplate for parent gridview
Add the below template to add collapsible option to parent GridView and child GridView will be hidden/shown for every row.
- <asp:TemplateField ItemStyle-Width="20px">
- <ItemTemplate> <a href="JavaScript:divexpandcollapse('div<%# Eval(" ID ") %>');">
- <img id="imgdiv<%# Eval("ID") %>" width="14px" border="0" src="../images/plus.png" />
- </a> </ItemTemplate>
- </asp:TemplateField>