Click here to Skip to main content
11,576,692 members (59,026 online)
Click here to Skip to main content

Freezing ASP.NET GridView Header With JavaScript and CSS

, 31 Oct 2008 CPOL 126.6K 3.6K 69
Rate this:
Please Sign up or sign in to vote.
Freeze an ASP.NET GridView header using JavaScript and CSS.

FreezeGridViewHeader

Introduction

Frozen header for an ASP.NET GridView is a common requirement for web developers nowadays. For usability reasons, frozen or fixed headers are a must for data viewing controls like DataGrid, GridView, or a raw HTML table etc. You must have observed that, in Excel, you can freeze the header cells of your spread sheet. When you scroll down, the headers are always visible, making your sheet more readable. The same effect is often needed in a GridView control, especially if you are displaying many records at a time. In this article, I will explain a technique that will allow you to achieve this with ease.

Conceptual Discussions

We all know that after executing the server-side code, raw HTML is returned to the browser, and the browser just shows the HTML. Obviously, a GridView needs to be converted to an HTML table. So, we need to do some customizations on the returned table to reach our goal. There are some steps to do that customization that are mentioned below:

  1. Take away the table row which usually represents the header and assign it to a newly created “<THEAD>” tag.
  2. Make the rest of table/grid row scrollable by limiting the height of the table and adding the “overflow: auto” attribute inside both “<TBODY>” and “<DIV>”. “<DIV>” is simply a wrapper over the grid which helps to represent the scrollable option.
  3. Now, fix/freeze the “<THEAD>” using a technique applicable to the browser (because different browsers act differently in this case).

Now, whenever you scroll the grid rows, the header always stays on the top row.

Using the Code

The complete sample code is given below. You can also download the sample project from the above link.

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

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

<style type="text/css">
    .WrapperDiv 
    {
        width:560px;height:290px;border: 1px solid black;
    }        
    .WrapperDiv TH 
    {
        /* Needed for IE */
         position: relative;
    }
    .WrapperDiv TR 
    {
        /* Needed for IE */
        height:0px;
    }
    .ScrollContent 
    {
        /* Needed for Opera */
        display: block;
        overflow: auto;
        width: 100%;
        height: 250px;
    }
    .FixedHeader
    {
        /* Needed for opera */
        display: block;
    }
    
</style>

<script runat="server">
  ICollection CreateDataSource( )
  {
    System.Data.DataTable dt = new System.Data.DataTable();
    System.Data.DataRow dr;
    dt.Columns.Add(new System.Data.DataColumn("Product Id", typeof(System.String)));
    dt.Columns.Add(new System.Data.DataColumn("Product Name", typeof(System.String)));
    dt.Columns.Add(new System.Data.DataColumn("Product Price", typeof(System.Decimal)));
    dt.Columns.Add(new System.Data.DataColumn("Manufacture Time", typeof(System.String)));
    dt.Columns.Add(new System.Data.DataColumn("Expired Time", typeof(System.String)));
    
    for (int i = 1; i <= 50; i++)
    {
      System.Random rd = new System.Random(Environment.TickCount * i); ;
      dr = dt.NewRow();
      dr[0] = i.ToString();
      dr[1] = "Sample Product" + i.ToString();
      dr[2] = System.Math.Round(rd.NextDouble() * 100, 2);
      dr[3] = "September/2008";
      dr[4] = "September/2012";
      dt.Rows.Add(dr);
    }
    System.Data.DataView dv = new System.Data.DataView(dt);
    return dv;
  }

  protected void Page_Load( object sender, EventArgs e )
  {
    if (!IsPostBack)
    {
      GridView1.DataSource = CreateDataSource();
      GridView1.DataBind();
    }
  }
  
</script>

<script type="text/ecmascript">

    var headerHeight = 8;

    /// <summary>
    ///  Responsible for call appropriate function according to browser
    ///  for Browser Compatibility
    /// </summary>
    function onLoad()
    {
        if(navigator.appName == "Opera")
        {
            freezeGridViewHeaderForOpera('GridView1');
        }
        else
        {
            freezeGridViewHeaderForIEAndFF('GridView1','WrapperDiv');
        }
    }
    
    /// <summary>
    ///  Used to create a fixed GridView header and allow scrolling
    ///  for IE and FF (Tested in IE-7 and FF-3.0.3)
    /// </summary>
    /// <param name="gridViewId" type="String">
    ///   Client-side ID of the GridView control
    /// </param>
    /// <param name="wrapperDivCssClass" type="String">
    ///   CSS class to be applied to the GridView's wrapper div element.
    /// </param>
    function freezeGridViewHeaderForIEAndFF(gridViewId,wrapperDivCssClass) 
    {
        var grid = document.getElementById(gridViewId);
        if (grid != 'undefined')
        {
            grid.style.visibility = 'hidden';
            
            var div = null;
            if (grid.parentNode != 'undefined') 
            {
                //Find wrapper div output by GridView
                div = grid.parentNode;
                if (div.tagName == "DIV")
                {
                    div.className = wrapperDivCssClass;  
                    div.style.overflow = "auto";             
                }
            }  
                       
            var grid = prepareFixedHeader(grid);
            var tbody = grid.getElementsByTagName('TBODY')[0];
            
            //Needed for Firefox
            tbody.style.height = (div.offsetHeight -  headerHeight) + 'px';

            tbody.style.overflowX = "hidden";
            tbody.overflow = 'auto';
            tbody.overflowX = 'hidden';
             
            grid.style.visibility = 'visible';
        }
    }
    
    /// <summary>
    ///  Used to create a fixed GridView header and allow scrolling
    ///  for Opera (Tested in Opera-9.2)
    /// </summary>
    /// <param name="gridViewId" type="String">
    ///   Client-side ID of the GridView control
    /// </param>
    function freezeGridViewHeaderForOpera(gridViewId)
    {
        var grid = document.getElementById(gridViewId);
        if (grid != 'undefined')
        {
            grid = prepareFixedHeader(grid);

            var headers = grid.getElementsByTagName('THEAD')[0];
            headers.className = "FixedHeader";
            
            var tbody = grid.getElementsByTagName('TBODY')[0];
            tbody.className = "ScrollContent";
            var cells = tbody.childNodes[0];

            for(var i = 0; i < cells.childNodes.length;i++)
            {
                var tableCell = cells.childNodes[i];
                var tableCellWidth = getStyle(tableCell,'width')
                var headerCell = headers.childNodes[0].childNodes[i];

                var headerCellWidth = getStyle(headerCell,'width');

                if(widthPxToInt(tableCellWidth) > widthPxToInt(headerCellWidth))
                {
                    headerCell.style.width=(widthPxToInt(tableCellWidth) - 10) + "px";
                }
                else
                {
                    tableCell.style.width=(widthPxToInt(headerCellWidth) - 10) + "px";
                }
            }
        }
    }
    
    /// <summary>
    ///  Used to prepare a fixed GridView header
    /// </summary>
    /// <param name="grid" type="GridView">
    ///   The Reference Of GridView control
    /// </param>
    function prepareFixedHeader(grid)
    {
        //Find DOM TBODY element and  and 
        var tags = grid.getElementsByTagName('TBODY');
        if (tags != 'undefined')
        {
            var tbody = tags[0];
            
            var trs = tbody.getElementsByTagName('TR');

            if (trs != 'undefined') 
            {
                headerHeight += trs[0].offsetHeight;
                
                //Remove first TR tag from it        
                var headTR = tbody.removeChild(trs[0]);
                
                //create a new element called THEAD
                var head = document.createElement('THEAD');
                head.appendChild(headTR);
                
                //add to a THEAD element instead of TR so CSS styles
                //can be applied properly in both IE and FireFox
                grid.insertBefore(head, grid.firstChild);
            }
       }
       
       return grid;
    }
    
    function getStyle(oElm, strCssRule)
    {
        var strValue = "";
        if(document.defaultView && document.defaultView.getComputedStyle){
           strValue = document.defaultView.getComputedStyle(oElm, 
                               "").getPropertyValue(strCssRule);
        }
        else if(oElm.currentStyle){
            strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
                return p1.toUpperCase();
            });
            strValue = oElm.currentStyle[strCssRule];
        }
        return strValue;
    }
    
    /// <summary>
    ///  Used to convert from Pxel to Integer
    /// </summary>
    /// <param name="width" type="String">
    ///  Width of any thing like GridHeader,GridCell
    /// </param>    
    function widthPxToInt(width)
    {
        width = width.substr(0,width.length-2);
        return new Number(width);
    }
    
    
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:GridView ID="GridView1" runat="server" 
              Font-Size="12px" BackColor="#FFFFFF"
              GridLines="Both" CellPadding="4" Width="560px">
          <HeaderStyle BackColor="#EDEDED" Height="26px" />
        </asp:GridView>
    </div>
    </form>
</body>
</html>

<script type="text/ecmascript">   
    window.onload = onLoad();
</script>

Browser Compatibility

Since I have used JavaScript and CSS to solve this problem, there is no doubt that it will raise the question, “Is the solution compatible for all browsers?”. If you Google, you will find lots of solutions for this problem. But, I have not yet found any client-side solution that supports all the browsers. Most of the solutions support Firefox and IE. But, very few support Opera.

I did test my provided solution in FireFox-3.0.3 , IE-7, and Opera-9.2 and got successful results.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Razwan Kader
Software Developer (Senior) somewhere in...
Bangladesh Bangladesh
Working in a Nordic company, developing some really interesting solutions for GSM Mobile Service Providers in Bangladesh. I work as a senior software developer there. Developed framework of challenging web based application. Build and manage a complete dynamic accounting and inventory management system which is tag based software. Enjoy learning about latest technology. Main working arenas are asp.net 2.0/3.5.

You may also be interested in...

Comments and Discussions

 
GeneralGridView With Fixed Headers in Asp.Net Using C# and jQuery Pin
Binu198521-Jun-14 0:01
memberBinu198521-Jun-14 0:01 
GeneralMy vote of 5 Pin
anilbishaul15-Sep-13 21:46
memberanilbishaul15-Sep-13 21:46 
QuestionPerformance Pin
SumanRoy23-Dec-12 23:50
memberSumanRoy23-Dec-12 23:50 
QuestionIE8 / Chrome / Visual Studio 2010 Pin
Scott Vincent19-Jun-12 14:34
memberScott Vincent19-Jun-12 14:34 
Generalnot worked in IE8 Pin
Moosdau24-Apr-11 3:45
memberMoosdau24-Apr-11 3:45 
GeneralRe: not worked in IE8 [modified] Pin
greentea_60029-Jul-11 17:24
membergreentea_60029-Jul-11 17:24 
Generalchrome related Pin
fdfsdfdfd21-Dec-10 19:12
memberfdfsdfdfd21-Dec-10 19:12 
GeneralScript is not working Pin
cliff clavin4-Jan-10 8:16
membercliff clavin4-Jan-10 8:16 
GeneralFreezing header and left columns in table using jquery Pin
manisha67616-Dec-09 5:51
membermanisha67616-Dec-09 5:51 
I want to know if there is a way to use jquery for freezing header and columns.We have big data,and because of performance issue want to use something with jquery.I am new in .net.Please help me.
Generalusing this code in vb Pin
loxzide30-Sep-09 17:04
memberloxzide30-Sep-09 17:04 
GeneralFreeze header. freeze footer and freeze left column Pin
sandeepkumars10-Aug-09 1:07
membersandeepkumars10-Aug-09 1:07 
Generalworks in ie 6,7 but not 8 Pin
walshy00720-Jul-09 3:52
memberwalshy00720-Jul-09 3:52 
GeneralRe: works in ie 6,7 but not 8 Pin
Member 391887021-Jul-09 9:32
memberMember 391887021-Jul-09 9:32 
GeneralExample in Visual Basic Pin
Revalk1-Jul-09 9:45
memberRevalk1-Jul-09 9:45 
General**Horizontal scroll bar** Pin
scorpioyas1-Jul-09 0:32
memberscorpioyas1-Jul-09 0:32 
Generaltable header in IE overlap the scroll bar Pin
MB_198118-Jun-09 20:33
memberMB_198118-Jun-09 20:33 
Generalin IE on scroll it show the text behind the header [modified] Pin
MB_198116-Jun-09 21:18
memberMB_198116-Jun-09 21:18 
Questionhow to remove the horizontal bar Pin
MB_198115-Jun-09 19:47
memberMB_198115-Jun-09 19:47 
GeneralVery Good - Just need some tweaks for Chrome/Safari Pin
andrew6ger19-May-09 3:52
memberandrew6ger19-May-09 3:52 
Generalfreeze the header & Column of gridview Pin
nadeem20031-Feb-09 19:43
membernadeem20031-Feb-09 19:43 
GeneralProblem when executing with grid view in content pages Pin
Qot15-Jan-09 20:03
memberQot15-Jan-09 20:03 
GeneralRe: Problem when executing with grid view in content pages Pin
DrShrinker22-Apr-09 8:27
memberDrShrinker22-Apr-09 8:27 
QuestionWhat about sorting? Pin
eashwar v19-Dec-08 18:44
membereashwar v19-Dec-08 18:44 
GeneralCouple of problems I noticed after building the sample... Pin
Justin Freitas1-Nov-08 3:32
memberJustin Freitas1-Nov-08 3:32 
GeneralRe: Couple of problems I noticed after building the sample... [modified] Pin
Razwan Kader1-Nov-08 18:51
memberRazwan Kader1-Nov-08 18:51 
GeneralRe: Couple of problems I noticed after building the sample... Pin
Greg Hazzard14-Dec-08 1:50
memberGreg Hazzard14-Dec-08 1:50 
GeneralWell done Pin
BigJim6131-Oct-08 13:05
memberBigJim6131-Oct-08 13:05 
GeneralRe: Well done Pin
Razwan Kader1-Nov-08 19:07
memberRazwan Kader1-Nov-08 19:07 
Generalnice article Pin
nhm tanveer hossain khan (hasan)31-Oct-08 12:35
membernhm tanveer hossain khan (hasan)31-Oct-08 12:35 
GeneralRe: nice article Pin
Razwan Kader1-Nov-08 19:08
memberRazwan Kader1-Nov-08 19:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150603.1 | Last Updated 31 Oct 2008
Article Copyright 2008 by Razwan Kader
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid