Fixed Header in GridView, cross-browser compatible

it involves taking the HeaderRow generated from the GridView, and then using javascript to copy its contents to a separate table outside the scrollable panel(it works in FireFox and IE)
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Fixedheader.aspx.cs" Inherits="Fixedheader" %>

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

    <script language="javascript">
<!--
        function createNonScrollableHeader(curHdrRowID, newHdrRowID) {
            var curHdrRow = document.getElementById(curHdrRowID);
            var newHdrRow = document.getElementById(newHdrRowID);

            copyAttributes(curHdrRow, newHdrRow);

            // The following line works with FireFox but not IE...would've made it a hell of a lot easier
            //newHdrRow.innerHTML = curHdrRow.innerHTML;

            //Instead we have to copy each individual cell
            for (var i = 0; i < curHdrRow.cells.length; i++) {
                var curHdrCell = curHdrRow.cells.item(i);
                var newHdrCell = document.createElement('th');
                copyAttributes(curHdrCell, newHdrCell);
                newHdrCell.innerHTML = curHdrCell.innerHTML;
                newHdrRow.appendChild(newHdrCell);
            }

            curHdrRow.style.display = "none";
        }


        // This needs some work, I'm only copying the attributes I know will be used ahead of time
        function copyAttributes(src, cpy) {
            if (src.style.width != "") cpy.style.width = src.style.width;
            if (src.style.height != "") cpy.style.height = src.style.height;
            if (src.style.color != "") cpy.style.color = src.style.color;
            if (src.style.backgroundColor != "") cpy.style.backgroundColor = src.style.backgroundColor;
            if (src.style.fontSize != "") cpy.style.fontSize = src.style.fontSize;
            if (src.style.fontWeight != "") cpy.style.fontWeight = src.style.fontWeight;
            if (src.style.fontFamily != "") cpy.style.fontFamily = src.style.fontFamily;
            if (src.style.textAlign != "") cpy.style.textAlign = src.style.textAlign;
            if (src.align != "") cpy.align = src.align;
            if (src.scope != "") cpy.scope = src.scope;
        }
//-->
    </script>

</head>
<body>
    <form id="form1" runat="server">
    <div>
        <!-- This is the table that will display the fixed header -->
        <asp:Table ID="tblHeader" runat="Server" BorderWidth="1" GridLines="Both" CellPadding="1"
            CellSpacing="0">
            <asp:TableHeaderRow ID="trHeader" runat="server">
            </asp:TableHeaderRow>
        </asp:Table>
        <asp:Panel ID="pnlGrid" runat="server" Height="300" ScrollBars="vertical" Width="530">
            <!-- The generated Header Row from this Grid will be copied to the above table,
and then the Grid's Header Row will be hidden -->
            <asp:GridView ID="gvCustomerList" runat="server" AllowPaging="False" CellPadding="1"
                CellSpacing="0" AllowSorting="True" ShowHeader="True" AutoGenerateColumns="false"
                OnPreRender="gvCustomerList_PreRender" OnSelectedIndexChanging="gvCustomerList_SelectedIndexChanging"
                OnSorting="gvCustomerList_Sorting">
                <HeaderStyle HorizontalAlign="center" />
                <Columns>
                    <asp:BoundField DataField="FirstName" SortExpression="FirstName" HeaderText="FirstName"
                        ItemStyle-Width="200" HeaderStyle-Width="200" />
                    <asp:BoundField DataField="LastName" SortExpression="LastName" HeaderText="LastName"
                        ItemStyle-Width="100" HeaderStyle-Width="100" />
                    <asp:BoundField DataField="Address" SortExpression="Address" HeaderText="Address"
                        ItemStyle-Width="100" HeaderStyle-Width="100" />
                </Columns>
            </asp:GridView>
        </asp:Panel>
    </div>
    </form>
</body>
</html>
Code Behind
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class Fixedheader : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        if (!IsPostBack)
        {
            if (Session["dtTemp"] != null)
            {
                gvCustomerList.DataSource = Session["dtTemp"] as DataTable;

                gvCustomerList.DataBind();


            }
            else
            {
                gvCustomerList.DataSource = GetCustomMadeDataTable();


                gvCustomerList.DataBind();
            }
        }

    }
    public DataTable GetCustomMadeDataTable()
    {

        //Create a new DataTable object

        System.Data.DataTable objDataTable = new System.Data.DataTable();

        //Create three columns with string as their type

        objDataTable.Columns.Add("Id", typeof(string));
        objDataTable.Columns.Add("FirstName", typeof(string));
        objDataTable.Columns.Add("LastName", typeof(string));
        objDataTable.Columns.Add("Address", typeof(string));
        objDataTable.Columns.Add("Email", typeof(string));
        DataRow dr;
        //Adding some data in the rows of this DataTable
        for (int i = 0; i <= 50; i++)
        {
            dr = objDataTable.NewRow();
            dr[0] = i.ToString();
            dr[1] = "FirstName" + i.ToString();
            dr[2] = "LastName" + i.ToString();
            dr[3] = "Address" + i.ToString();
            dr[4] = "Email" + i.ToString();
            objDataTable.Rows.Add(dr);
        }
        DataColumn[] dcPk = new DataColumn[1];
        dcPk[0] = objDataTable.Columns["Id"];
        objDataTable.PrimaryKey = dcPk;
        Session["dtTemp"] = objDataTable;
        return objDataTable;
    }
    protected void gvCustomerList_PreRender(object sender, EventArgs e)
    {
        pnlGrid.Width = gvCustomerList.Width; string jvScript = "";
        Page.ClientScript.RegisterStartupScript(this.GetType(), "CreateNonScrollableHeader", jvScript);
    }
    protected void gvCustomerList_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
    {

    }
    protected void gvCustomerList_Sorting(object sender, GridViewSortEventArgs e)
    {
        DataTable dt = Session["dtTemp"] as DataTable;


        DataView dv = new DataView(dt);


        dv.Sort = e.SortExpression;
        gvCustomerList.DataSource = dv;

        this.DataBind();
    }

}
The only problems with this solution are that you have to be precise when you define the width's of your columns in the grid for both the ItemStyle-Width and the HeaderStyle-Width, making sure that they are set to be the same, and have enough width so that the populating text will not push the cell out and throw your alignment out of whack.. And, you must also make sure that the generated html table by the grid, and the table that will hold the fixed header have the same attributes (CellPadding, CellSpacing, etc.).
Reactions

Post a Comment

2 Comments

  1. What will be the value for
    curHdrRowID and newHdrRowID
    in the JS method createNonScrollableHeader(curHdrRowID, newHdrRowID)

    ReplyDelete
  2. I have gone through your code for fix the header of the Gridview and also I have check it in FireFox and IE , But its not working. So please give any suggestion for this.

    ReplyDelete

Please do not post any spam link in the comment box😊

Emoji
(y)
:)
:(
hihi
:-)
:D
=D
:-d
;(
;-(
@-)
:P
:o
:>)
(o)
:p
(p)
:-s
(m)
8-)
:-t
:-b
b-(
:-#
=p~
x-)
(k)

Close Menu