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.