Geeks With Blogs


Microsoft MVP


Moderator at CodeASP.NET

Quiz Master

free counters
Free counters
Added on January 19,2012

Follow Me @vmsdurano

A bit About Me

The opinions expressed herein are my own personal opinions and does not represent the opinions of my employers. Nor does it represent the opinion of my dog, because I don’t have one.

Vinz' Blog (ProudMonkey) "Code, Beer and Music ~ my way of being a programmer"
Technorati Tags: ,,


Many developers from the forums ( are asking if how to implement fix header in GridView while scrolling. We all know that there are lots of examples out there that provide a solution that are available, however some of the solutions provided are not cross browser compatible. While searching for a cross browser solution, I found this article at and it seems very interesting to me. So I play around with the extender provided by devarchive team and thought what if I also wanted to show the footer while scrolling the Grid?So I decided to extend the control a little bit further and added the fix footer while scrolling the rows in the GridView. See the sample screen shots below:








Note:I will not elaborate more about the implementation of the extender so before you proceed I would suggest you to read and download the original source codes at first.


Here are the updated codes below:




using System;

using System.Collections.Generic;

using System.Text;

using System.Web.UI.Design;

using System.Globalization;

using System.Web.UI;


namespace GridBox


    public class GridBoxDesigner : ControlDesigner



        private const string StandardDesignTimeHtml =

        @"<table style=""border:1px solid #CCCCCC;"" cellspacing=""0"" cellpadding=""0"">


        <td nowrap


        <strong>{0}</strong> - {1}</td>




        public override string GetDesignTimeHtml()
















using System;

using System.Collections.Generic;

using System.Text;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.ComponentModel;

using System.ComponentModel.Design;

using System.Web;

using System.Security.Permissions;


namespace GridBox



        AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal),

        AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),

        Designer("GridBox.SimpleDesigner, GridBox"),

        ToolboxData("<{0}:GridBoxExtender runat=server></{0}:GridBoxExtender>"),



    public class GridBoxExtender : ExtenderControl


        #region Overrides

        protected override void OnLoad(EventArgs e) {




        protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl) {

            if (TargetControl == null || !TargetControl.Visible || TargetControl.Rows.Count == 0) {

                TargetControl.Height = Unit.Empty;

                yield break;


            ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor("GridBox.GridBoxExtender", targetControl.ClientID);

            descriptor.AddProperty("scrollField", HiddenFieldID);

            yield return descriptor;



        protected override IEnumerable<ScriptReference> GetScriptReferences() {

            if (TargetControl == null || !TargetControl.Visible || TargetControl.Rows.Count == 0) {

                TargetControl.Height = Unit.Empty;

                yield break;


            yield return new ScriptReference("GridBox.GridBoxExtender.js", this.GetType().Assembly.FullName);



        protected override void Render(HtmlTextWriter writer) {









        private GridView TargetControl {

            get {

                GridView result = this.NamingContainer.FindControl(TargetControlID) as GridView;

                return result;




        private int LastScroll {

            get {

                int result = 0;

                if (Page.Request[HiddenFieldID] != null) {

                    int.TryParse(Page.Request[HiddenFieldID], out result);


                return result;




        private string HiddenFieldID {

            get {

                return String.Format("{0}_GVFHE_Scroll", ClientID);









The JavaScript file:




/// <reference name="MicrosoftAjax.debug.js" />

/// <reference name="MicrosoftAjaxTimer.debug.js" />

/// <reference name="MicrosoftAjaxWebForms.debug.js" />




    GridBox.GridBoxExtender = function(element) {

    GridBox.GridBoxExtender.initializeBase(this, [element]);

    this._documentResizeDelegate = null;

    this._lock = false;

    this._mainTableID = null;

    this._innerTableID = null;

    this._divChild = null;


    this._scrollField = 0;



GridBox.GridBoxExtender.prototype = {

    // Overrides


    initialize: function() {

        GridBox.GridBoxExtender.callBaseMethod(this, 'initialize');



    dispose: function() {

        //Add custom dispose actions here

        $removeHandler(window, "resize", this._documentResizeDelegate);

        if (this._divChild) {



        GridBox.GridBoxExtender.callBaseMethod(this, 'dispose');




    // Properties


    get_scrollField: function() {

        return this._scrollField;



    set_scrollField: function(value) {

        if (this._scrollField !== value) {

            this._scrollField = value;






    // Methods


    getLastScroll: function() {

        var result = 0;

        var hf = $get(this._scrollField);

        if (hf) {

            result = parseInt(hf.value);

            if (!result) result = 0;


        return result;


    setLastScroll: function(value) {

        var hf = $get(this._scrollField);

        if (hf) {

            hf.value = value;



    initGrid: function() {

        // create deep clone of target grid

        var target = this.get_element();

        var clone = target.cloneNode(true);


        // get desired height of inner scrollable area

        var height =;

        var width =;


        var mainTable = target.cloneNode(false); = String.format("outer_{0}",;

        target.parentNode.insertBefore(mainTable, target);



        var mainHead = document.createElement("thead");


        var mainBody = document.createElement("tbody");



        //**** ADDED FOOTER

        var mainFoot = document.createElement("tfoot");



        // Clone original header

        var header = target.rows[0].cloneNode(true);



        //**** ADDED FOOTER clone footer

        var footer = target.rows[target.rows.length - 1].cloneNode(true);



        // add scrollable area mainTable

        var secondRow = document.createElement("tr");


        var mainTd = document.createElement("td");


        this.setAttribute(mainTd, "colspan", target.rows[0].cells.length);

        this.setAttribute(mainTd, "align", "left");

        this.setAttribute(mainTd, "valign", "top");

        var divChild = document.createElement("div");

        mainTd.appendChild(divChild); = width; = height;

        $addHandler(divChild, "scroll", Function.createDelegate(this, this.syncScroll)); = "auto"; = "hidden"; = "scroll";

        this._divChild = divChild;


        //        Sys.UI.DomElement.addCssClass(divChild, "divScrollVertical");


        // now remove old grid from document and insert new clone into the place




        // assign extender related data to clone

        clone._behaviors = target._behaviors;

        clone.GridBoxExtender = target.GridBoxExtender;


        // correct styles

        var attributes = [];

        for (var i = 0; i < clone.attributes.length; i++) {

            var attr = clone.attributes.item(i);

            var value = attr.value.trim().toLowerCase();

            if (value != "cellpadding" && value != "cellspacing") {

                Array.add(attributes, attr);



        Array.forEach(attributes, this.deleteAttribute, clone);

        clone.deleteRow(0); //remove header row

        clone.deleteRow(clone.rows.length - 1); //remove 5footer

        clone.border = "0"; = "0px"; = "100%"; = ""; = ""; = "";



        // correct widths of header columns and subscribe to document resize event:

        this._mainTableID =;

        this._innerTableID =;

        this._documentResizeDelegate = Function.createDelegate(




        // Attach to window's resize event to resize header cells when inner cells change their size

        $addHandler(window, "resize", this._documentResizeDelegate);

        // Restore scroll position from last time 

        divChild.scrollTop = this.getLastScroll();



    setAttribute: function(element, attribute, value) {

        var namedItem = document.createAttribute(attribute);

        namedItem.value = value;



    deleteAttribute: function(attribute, index, attributes) {



    syncScroll: function(args) {

        if (this._divChild) {




    syncWidths: function(args) {

        if (!this._lock) {

            this._lock = true;

            var mainTable = $get(this._mainTableID);

            var innerCellPadding = mainTable.cellPadding;

            var header = mainTable.rows[0];

            var innerTable = $get(this._innerTableID);

            var originalRow = innerTable.rows[0];

            var headerWidth = Sys.UI.DomElement.getBounds(header).width;

            var originalRowWidth = Sys.UI.DomElement.getBounds(originalRow).width;

            var diff = headerWidth - originalRowWidth - innerCellPadding * 2;

            if (originalRow && header) {

                for (var i = 0; i < originalRow.cells.length; i++) {

                    var bounds = Sys.UI.DomElement.getBounds(originalRow.cells[i]);

                    var x = bounds.width;

                    if (i == originalRow.cells.length - 1) {

                        x = x + diff - innerCellPadding * 2;

                    } else {

                        x = x - innerCellPadding;


                    header.cells[i].style.width = x + "px";



            this._lock = false;





GridBox.GridBoxExtender.registerClass('GridBox.GridBoxExtender', Sys.UI.Behavior);



Usage of the Extender:


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


<%@ Register Assembly="GridBox" Namespace="GridBox" TagPrefix="cc1" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">


<html xmlns="">

<head runat="server">

    <title>GridBox Demo</title>

    <link href="CSS/GridBoxSample.css" rel="stylesheet" type="text/css" />



    <form id="form1" runat="server">

    <asp:ScriptManager ID="ScriptManager1" runat="server"/>

    <div style="width:500px">

        <asp:GridView ID="GridView1" runat="server" Width="100%" GridLines="None" ShowFooter="true"  AutoGenerateColumns="false" CssClass="gridbox" Height="150px">

        <RowStyle CssClass="data-row" />

        <FooterStyle CssClass="footer-style"/>


            <asp:TemplateField ItemStyle-Width="5%">


                <asp:CheckBox ID="CheckBoxAll" runat="server" Text="All" />



                <asp:CheckBox ID="CheckBoxSelect" runat="server" />





            <asp:BoundField DataField="TerminalNumber" HeaderText="Terminal #" ItemStyle-Width="10%"  />

            <asp:BoundField DataField="TransactionNumber" HeaderText="Transaction #" ItemStyle-Width="10%"/>

            <asp:BoundField DataField="OperatorNumber" HeaderText="Operator #" ItemStyle-Width="10%"/>

            <asp:BoundField DataField="OperatorName" HeaderText="Operator Name" ItemStyle-Width="10%"/>



       <cc1:GridBoxExtender ID="GridBoxExtender1" runat="server" TargetControlID="GridView1" />


    <asp:Button ID="Button1" runat="server" Text="Button" />





That was it! Hope you will find this post useful!


Again credits to (Kirill Chilingarashvili)

Posted on Wednesday, January 6, 2010 5:17 PM ASP.NET , C# , GridView | Back to top

Comments on this post: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...
how can implement ti on .NET 4 or 3.5
Left by Ali on Nov 16, 2010 2:25 PM

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...

I actually used 3.5 version when implementing that. =)
Left by Vinz on Nov 16, 2010 3:28 PM

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...
thanks alot , but when trying to implement it t, i cannot inherit from ControlDesigner .and ther're not class ExtenderControl ,

also what if I have no row in my grid view will the header and foter position be fixed

sorry but I am stil new to
Left by Ali on Nov 21, 2010 3:46 PM

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...
I need to fix the header and the footer without care of the number of rows
Left by Ali on Nov 21, 2010 7:54 PM

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...
Hello ,
actually i want to keep header and footer fix in position in GridView while scrolling.i think your article will be helpful for me.
I tried to do it by my own but i getting an error in GridBoxDesigner.cs file that "type/namespace 'control' could not be found " Please help me to resolve this problem . Please reply as soon as you possible .
Left by Natasha Borkar on Jun 21, 2011 4:11 PM

# re: FAQ: Cross Browser GridView Fix Header and Footer with ASP.NET Ajax
Requesting Gravatar...
i got the following error i.e error creating control...give me the solution wts the problem
Left by sena on Jul 31, 2011 10:08 PM

comments powered by Disqus

Copyright © Vincent Maverick Durano | Powered by: