Thursday, March 21, 2013

Freeze/persist ASP.NET GridView header (with images)

Hello,

From time to time we all get a nasty task like 'freeze the grid header and if it is possible do it for most browsers'.
In my case the grid was and ASP.NET WebForms GridView. There are many solutions online (jQuery plugins of some CSS stuff) regarding this but in my case none of those worked by default. What was different in my case was the header; the header cells were some images generated by some aspx file.
The default behavior of the solutions I found was that the header was not in sync with the text cells. This happens because the images were not loaded when the table element (the gridview) was generated.
These are the steps that worked for me:
1. Set the GridView to have thead as header and tbody as body. In RowDataBound set the GridView.HeaderRow.TableSection = TableRowSection.TableHeader;
2. Use the idea from here: http://css-tricks.com/snippets/jquery/persistant-headers-on-tables/
3. Modify a little bit the code to wait for loading images and then modify the width of the th elements:

    window.onload = function () {
        $("table.tableWithFloatingHeader").each(function () {
            $(this).wrap("
");
            $("tr:first", this).before($("tr:first", this).clone());
            clonedHeaderRow = $("tr:first", this);
            clonedHeaderRow.addClass("tableFloatingHeader");
            clonedHeaderRow.css("position", "absolute");
            clonedHeaderRow.css("top", "0px");
            clonedHeaderRow.css("left", "0px");
            clonedHeaderRow.css("visibility", "hidden");

            var row_ths = $("tr:nth-child(2)", this).children("th");
            var crow_ths = $("tr:nth-child(1)", this).children("th"); ;

            for (var i = 0; i < row_ths.size(); ++i) {
                crow_ths.eq(i).width(row_ths.eq(i).width() + 2);
            }
        });

That's about it!