Solución jQuery para encabezado fijo en controles asp:GridView y dx:ASPxGridView

Para lograr encabezados fijos en controles como asp:GridView y dx:ASPxGridView, se emplea jQuery con dos métodos principales. El primero utiliza position: fixed para mejor rendimiento, aunque no es compatible con IE6 o Safari anterior a iOS5. El segundo aplica position: absolute con eventos de scrolll, ofreciendo mayor compatibilidad con navegadores antiguos. A continuación, se presenta una implementación refactorizada que altera la estructura del código, nombres de variables y lógica, manteniendo la funcionalidad.

Implementación para asp:GridView

Este código crea un plugin jQuery para asp:GridView, clonando la fila del encabezado y posicionándola de manera fija al hacer scroll.

<script type="text/javascript">
(function($) {
    $.fn.stickyHeader = function(settings) {
        var headerExists = false;
        var tableSelector = this;
        var clonedHeaderId = 'sticky-header-table';

        $(window).on('scroll', function() {
            try {
                var targetRow = tableSelector.find('tr:first');
                var triggerPoint = targetRow.offset().top + targetRow.outerHeight();
                var currentScroll = $(window).scrollTop();

                if (triggerPoint <= currentScroll) {
                    if (!headerExists) {
                        headerExists = true;
                        var horizontalOffset = targetRow.offset().left;
                        var headerRowClone = targetRow.clone();
                        var headerCells = headerRowClone.find('th');
                        var dataCells = tableSelector.find('tr:eq(1) td');

                        // Ajustar anchos de celdas
                        for (var index = 0; index < headerCells.length; index++) {
                            $(headerCells[index]).width($(dataCells[index]).width());
                        }

                        // Crear tabla fija
                        var fixedTable = $('<table></table>', {
                            id: clonedHeaderId,
                            css: {
                                position: 'fixed',
                                top: '0px',
                                left: horizontalOffset + 'px'
                            }
                        }).append(headerRowClone).prependTo('body');

                        // Compatibilidad con IE6
                        if (navigator.userAgent.match(/MSIE 6/)) {
                            fixedTable.css('position', 'absolute');
                            $(window).add(document.body).on('scroll resize', function() {
                                fixedTable.css('top', document.documentElement.scrollTop || document.body.scrollTop + 'px');
                            });
                        }
                    }
                } else {
                    if (headerExists) {
                        headerExists = false;
                        $('#' + clonedHeaderId).remove();
                    }
                }
            } catch (error) {
                console.error('Error en stickyHeader:', error);
            }
        });
    };
})(jQuery);

// Invocación del plugin
$(document).ready(function() {
    $('#<%=GridView1.ClientID %>').stickyHeader();
});
</script>

Implementación para dx:ASPxGridView

Para dx:ASPxGridView, la estructura interna del control requiere un enfoque ligeramente distinto, extrayendo la tabla y clonando la primera fila.

<script type="text/javascript">
(function($) {
    $.fn.fixedHeaderGrid = function() {
        var gridControl = this;
        var isHeaderVisible = false;
        var headerTableId = 'fixed-header-wrapper';

        $(window).on('scroll', function() {
            try {
                var gridTable = gridControl.find('table').first();
                var headerRow = gridTable.find('tr').first();
                var scrollThreshold = headerRow.offset().top + headerRow.outerHeight();
                var scrollPosition = $(window).scrollTop();

                if (scrollThreshold <= scrollPosition) {
                    if (!isHeaderVisible) {
                        isHeaderVisible = true;
                        var leftPosition = headerRow.offset().left;
                        var cellStyle = gridTable.find('td:first').attr('class');

                        // Construir tabla de encabezado fijo
                        var headerHtml = '<table id="' + headerTableId + '" cellspacing="0" cellpadding="0" style="position:fixed;top:0;left:' + leftPosition + 'px;font-size:12px;"><tr>';
                        headerRow.find('td').each(function() {
                            var cellWidth = $(this).outerWidth();
                            var cellText = $(this).text();
                            headerHtml += '<td class="' + cellStyle + '" style="border-top:0;border-left:0;width:' + cellWidth + 'px">' + cellText + '</td>';
                        });
                        headerHtml += '</tr></table>';

                        // Insertar y aplicar clase del grid
                        var fixedHeader = $(headerHtml).addClass(gridTable.attr('class')).prependTo('body');

                        // Fallback para IE6
                        if ($.browser && $.browser.msie && $.browser.version === '6.0') {
                            fixedHeader.css('position', 'absolute');
                            var headerElement = document.getElementById(headerTableId);
                            window.onscroll = function() {
                                headerElement.style.top = (document.documentElement.scrollTop || document.body.scrollTop) + 'px';
                            };
                            window.onresize = window.onscroll;
                        }
                    }
                } else {
                    if (isHeaderVisible) {
                        isHeaderVisible = false;
                        $('#' + headerTableId).remove();
                    }
                }
            } catch (e) {
                console.error('Error en fixedHeaderGrid:', e);
            }
        });
    };
})(jQuery);

// Invocación
$(document).ready(function() {
    $('#<%=ASPxGridView1.ClientID %>').fixedHeaderGrid();
});
</script>

Consideraciones importantes

Al usar código del lado del servidor como <%=Control.ClientID %>, coloque los scripts dentro del bloque <body> para evitar errrores de modificación de controles en ASP.NET. La versión refactorizada elimina dependencias de $.browser y usa detección de userAgent para IE6, mejorando la robustez. Los métodos alternativos con position: absolute se integran directamente en la lógica de scroll para compatibilidad universal.

Etiquetas: asp:GridView dx:ASPxGridView jQuery fixed-header web-development

Publicado el 6-14 03:58