Monday, January 25, 2010

Master Detail representation using Nested Gridview




Introduction
A recurring task in software development is representing tabular data in master detail format. ASP.Net provides a number of tools for performing this task.  Here I will show how to use nested grid view to show detail data related to master table on asp.net web page.
Technique
Take a grid view that display data from master table. Create last column of this grid as TemplateField. Inside this TemplateField, take another girdview to display data from detail table. Bind detail grid view in OnRowDataBound event of master grid view with related data of respective row.
Defining Task
We will bind departments of a company in a CheckedList box. We want to display employee information of selected departments to gridview. Master grid will bind department names and Detail grid will display employee information of respective department.
Expected Output:



Writing HTML code:
HTML codes should look like following:
<table border="0" cellpadding="0" cellspacing="0" width="100%">
                <tr>
                    <td align="center" colspan="3">
                        <asp:Label ID="lblTableHeader" runat="server" CssClass= "TableHeader" >asp:Label>
                    td>
                tr>
<tr>
                    <td align="right">
                        <asp:Label ID="lblDept" runat="server" Text="Select Department:" Font-Bold="True">asp:Label>
                    td>
                    <td align="left">
                        <asp:CheckBoxList ID="lstDepartmentName" runat="server" Height="100px" RepeatColumns="4">
                            <asp:ListItem>DepartmentNameasp:ListItem>
                        asp:CheckBoxList>
                    td>
                    <td>
                         
                    td>
                tr>
<tr>
                    <td align="right">
                        <asp:Label ID="lblEmptype" runat="server" Font-Bold="True" Text="Select Employee Type:">asp:Label>
                    td>
                    <td>
                         
                        <asp:DropDownList ID="ddlEmpType" runat="server">
                        asp:DropDownList>
                    td>
                    <td>
                         td>
                tr>
<tr>
                    <td align="right">
                        <asp:Button ID="btnPreview" runat="server" CssClass="Button" OnClick="btnPreview_Click"
                            Text="Preview" Width="105px" />
                    td>
                    <td>
                         
                    td>
                    <td>
                         td>
                tr>
<tr>
                    <td align="center" colspan="3">
                        <asp:GridView ID="gvDeptNameList" runat="server" AutoGenerateColumns="False" BackColor="White"
                            BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" EmptyDataText="No rows returned"
                            OnRowDataBound="gvDeptNameList_RowDataBound" Width="100%">
                            <RowStyle ForeColor="#000066" />
                            <Columns>
                                <asp:BoundField DataField="DepartmentName" HeaderText="Department" SortExpression="DepartmentName">
                                    <ItemStyle VerticalAlign="Top" />
                                asp:BoundField>
                                <asp:TemplateField HeaderText="Employee Inforamtion">
                                    <ItemTemplate>
                                        <asp:GridView ID="gvEmpLstByDeptAndEmpType" runat="server" AutoGenerateColumns="False" BackColor="White" BorderColor="#CCCCCC" BorderStyle="Solid" BorderWidth="1px" CellPadding="3" EmptyDataText="No Employees"
Width="100%">
                                            <RowStyle ForeColor="#000066" />
                                            <Columns>
                                                <asp:BoundField DataField="StaffCode" HeaderText="Staff Code" SortExpression="StaffCode">
                                                    <ItemStyle Width="100px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="LastName" HeaderText="Employee Name" SortExpression="Name">
                                                    <ItemStyle Width="200px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="DesignationName" HeaderText="Designation" SortExpression="Designation">
                                                    <ItemStyle Width="400px" />
                                                asp:BoundField>
                                                <asp:BoundField DataField="GradeName" HeaderText="Grade" SortExpression="GradeName">
                                                    <ItemStyle Width="100px" />
                                                asp:BoundField>
                                            Columns>
                                            <HeaderStyle BackColor="#D6E6EB" Font-Bold="True" ForeColor="Black" />
                                        asp:GridView>
                                    ItemTemplate>
                                asp:TemplateField>
                            Columns>
                            <FooterStyle BackColor="White" ForeColor="#000066" />
                            <HeaderStyle BackColor="#006699" Font-Bold="True" ForeColor="White" />
                            <PagerStyle BackColor="White" ForeColor="#000066" HorizontalAlign="Left" />
                            <SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
                        asp:GridView>
                        <asp:HiddenField ID="hfSortExp" runat="server" />
                        <asp:HiddenField ID="hfWhereCondition" runat="server" />
                        <asp:HiddenField ID="hfddlEmpType" runat="server" />
                    td>
                tr>
table>

Notice in above HTML code I have taken gvDeptNameList to display department list.  Here I have taken two columns. First one to display department name and second on to display related employee information of the department. Second column is TempalteField and contain Detail grid.
Code:
Now we will see back end C# code step by step:
Step1: Populate departments on Page_Load
protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                BindDepartmnets();
                lblTableHeader.Text = "Departemt Wise Employee List";
            }
            SetPageTitle("Departemt Wise Employee List");

        }
public void BindDepartmnets()
        {
            lstDepartmentName.DataSource = oHR_ReportBLL.EmployeeList_GetDistinctDepartments(CustomQueries.VW_EMPLOYEELIST_GETDDISTINCT_DEPARTMENTS);
            lstDepartmentName.DataTextField = "DepartmentName";
            lstDepartmentName.DataValueField = "DepartmentName";
            lstDepartmentName.DataBind();
        }

Step2: Populate Department on btnPreview_Click
protected void btnPreview_Click(object sender, EventArgs e)
        {
            //Get list of selected departments
            List<Department> departmentList = new List<Department>();

            for (int i = 0; i <= lstDepartmentName.Items.Count - 1; i++)
            {
                Department department = new Department();
                ListItem lst = lstDepartmentName.Items[i];
                if (lst.Selected)
                {
                    if (departmentList.Count == 0)
                    {
                        department.DepartmentName = lst.Text;
                        departmentList.Add(department);
                    }
                    else
                    {
                        department.DepartmentName = lst.Text;
                        departmentList.Add(department);
                    }
                }
            }


            gvDeptNameList.DataSource = departmentList;
            gvDeptNameList.DataBind();

        }
Step3: Populate gvEmpLstByDeptAndEmpType on gvDeptNameList_RowDataBound
protected void gvDeptNameList_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType == System.Web.UI.WebControls.DataControlRowType.DataRow)
            {
                Department department = (Department)e.Row.DataItem;
                GridView gvEmpLstByDeptAndEmpType = (GridView)e.Row.FindControl("gvEmpLstByDeptAndEmpType");

                WhereCondition = " DepartmentName in('" + department.DepartmentName + "') ";
                if (ddlEmpType.SelectedIndex > 0)
                {
                    WhereCondition += " and EmployeeTypeName='" + ddlEmpType.SelectedItem.Text + "'";
                }
                OrderbyClause = " DesignationGroupRank ";
                BindListEmpByDeptAndEmpType(WhereCondition, OrderbyClause, gvEmpLstByDeptAndEmpType);
            }
        }
public void BindListEmpByDeptAndEmpType(string WhereCondition, string orderByExpression, GridView gv)
        {
            List<Hr_GetEmployeesByDeartmentAndEmployeeType> lstHr_GetEmployeesByDeartmentAndEmployeeType = oHR_ReportBLL.Report_Hr_GetEmployeesByDeartmentAndEmployeeType(WhereCondition, orderByExpression);
            gv.DataSource = lstHr_GetEmployeesByDeartmentAndEmployeeType;
            gv.DataBind();
        }
Here notice that I find gridview gvEmpLstByDeptAndEmpType inside row of gvDeptNameList that is binding its row data. Then bind related employee information to gvEmpLstByDeptAndEmpType.

Conclusion
Here I have illustrated how you can extend the functionality of GridView control to display related data by using nested GridView controls on an ASP.NET Web page. You can also extend your application to enable data to be updated and deleted or enable users to insert new records.




1 comment: