Click here to Skip to main content
6,305,776 members and growing! (17,063 online)
Email Password   helpLost your password?
Web Development » ASP.NET Controls » Grid Controls     Intermediate License: The Code Project Open License (CPOL)

Freezing ASP.NET GridView Header With JavaScript and CSS

By Razwan Kader

Freeze an ASP.NET GridView header using JavaScript and CSS.
C# (C# 2.0, C# 3.0), Javascript, CSS, .NET, ASP.NET, Dev
Version:2 (See All)
Posted:31 Oct 2008
Views:16,871
Bookmarked:38 times
Announcements
Loading...
 
Search    
Advanced Search
printPrint   Broken Article?Report       add Share
  Discuss Discuss   Recommend Article Email
8 votes for this article.
Popularity: 3.93 Rating: 4.36 out of 5

1

2
1 vote, 12.5%
3
3 votes, 37.5%
4
4 votes, 50.0%
5

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)

About the Author

Razwan Kader


Member
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.
Occupation: Software Developer (Senior)
Company: somewhere in...
Location: Bangladesh Bangladesh

Other popular ASP.NET Controls articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 17 of 17 (Total in Forum: 17) (Refresh)FirstPrevNext
GeneralExample in Visual Basic PinmemberRevalk10:45 1 Jul '09  
General**Horizontal scroll bar** Pinmemberscorpioyas1:32 1 Jul '09  
Generaltable header in IE overlap the scroll bar PinmemberMB_198121:33 18 Jun '09  
Generalin IE on scroll it show the text behind the header [modified] PinmemberMB_198122:18 16 Jun '09  
Generalhow to remove the horizontal bar PinmemberMB_198120:47 15 Jun '09  
GeneralVery Good - Just need some tweaks for Chrome/Safari Pinmemberandrew6ger4:52 19 May '09  
Generalfreeze the header & Column of gridview Pinmembernadeem200320:43 1 Feb '09  
GeneralProblem when executing with grid view in content pages PinmemberQot21:03 15 Jan '09  
GeneralRe: Problem when executing with grid view in content pages PinmemberDrShrinker9:27 22 Apr '09  
GeneralWhat about sorting? Pinmembereashwar v19:44 19 Dec '08  
GeneralCouple of problems I noticed after building the sample... PinmemberJustin Freitas4:32 1 Nov '08  
GeneralRe: Couple of problems I noticed after building the sample... [modified] PinmemberRazwan Kader19:51 1 Nov '08  
GeneralRe: Couple of problems I noticed after building the sample... PinmemberGreg Hazzard2:50 14 Dec '08  
GeneralWell done PinmemberBigJim6114:05 31 Oct '08  
GeneralRe: Well done PinmemberRazwan Kader20:07 1 Nov '08  
Generalnice article Pinmembernhm tanveer hossain khan (hasan)13:35 31 Oct '08  
GeneralRe: nice article PinmemberRazwan Kader20:08 1 Nov '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 31 Oct 2008
Editor: Smitha Vijayan
Copyright 2008 by Razwan Kader
Everything else Copyright © CodeProject, 1999-2009
Web17 | Advertise on the Code Project