固定表头的实现方法

网页设计中,为了提高用户体验,经常需要实现一些智能的数据呈现方式。其中一种需求是固定表头行,以便用户在滚动页面时能够轻松地跟踪数据。不幸的是,标准的GridView控件并不提供这样的功能。虽然已经在网上搜索了很长时间,但没有找到满意的解决方案。因此,决定开发一个库来支持这个功能。以下是实现的结果。

在客户端绑定“滚动”事件是这项技术的核心。当表头行在滚动页面时即将消失时,整个行会从网格中分离出来,然后漂浮在浏览器的顶部。相反,当表头行重新出现在屏幕视图中时,它会重新加入网格,就像什么都没发生一样。

工作原理

冻结表头行是一个棘手的问题。使用jQuery来挂钩事件并关注表头行位置的变化。以下是代码示例:

<script type="text/javascript"> var gridview_header_top_position = 0; $(document).ready(function() { $(window).scroll(function() { if ($(window).scrollTop() >= top_position_of_header_row) { // 从网格中分离表头行并将其推到浏览器顶部: // 例如:jHeaderRow.css('position', 'fixed'); } else { // 将其放回原始位置: // 例如:jHeaderRow.css('position', ''); } }); }); </script>

上述代码片段不会增加服务器往返的处理开销。但是,在编写脚本时要小心,以免网页在响应每次滚动事件时变得迟钝。为了优化性能,请定义一些变量来保存不变或很少变化的数据,例如:网格视图的位置,表头行的副本...

浏览器兼容性

让网页在各种浏览器中运行顺畅并保持兼容性是一项艰巨的任务,以确保使用起来感觉像是在使用同一个浏览器。显然,为了让它跳过所有的障碍,必须对代码进行大量的微调。

上述解决方案在Firefox、Opera和Chrome中运行得很好。对于Safari和Flock,重新连接后布局会破裂。对于IE浏览器,它在8.0及以上版本中运行良好。对于IE 7.0、6.0或更低版本,看起来不好。IE 6不支持“fixed”位置。它必须使用一些CSS技巧来完成。但是CSS技巧不是一件好事,因为其他不相关的部分可能会受到影响。那么,为什么要为这样的问题付出巨大的努力呢?建议是,对于IE 6.0和7.0,如果不想承担巨大的成本,就让网格标题保持不冻结。

测试用例

有3个主要的场景可能不会在早期注意到:

测试用例 #1:

当表头被冻结时,表头行和数据行的单元格比例失调。就像下面的图片一样:

这个错误发生在GridView控件中设置单元格样式时。当整个表头被取出并定位在浏览器顶部(或停靠在任何预定义框架的顶部)时,列会失去“前导样式设置”(由表头单元格规定),而ItemStyle-Width将被应用。

<asp:TemplateField ItemStyle-Width="80px" HeaderText="Customer ID"> <ItemTemplate> <asp:Label ID="lblCustID" runat="server" Text='<%# Eval("CustomerID") %>'></asp:Label> </ItemTemplate> </asp:TemplateField>

给这个错误一个完美的修复并不容易。可能需要逐个微调断开连接的表头,以确保它与网格非常紧密地配合。如果不想为所有这些事情头疼,让采用文章最后解释的完整解决方案。

测试用例 #2:

断开连接的表头不会随着底层表格/网格在水平滚动页面时一起移动。为什么?因为将它们设置为固定(position = 'fixed'),所以它不会移动。

为了解决上述错误,提出了一个全新的解决方案。克隆了整个表格并将其放入一个新的层(div)。这个层停靠在顶部,但在滚动页面时会移动。让看看下面的图片是如何描述的:

<script type="text/javascript"> $(window).bind('resize', function () { // 代码放在这里,重新计算克隆表格的宽度,使其与底层表格的新宽度值相同。 }); </script>

请注意,这个解决方案可能会让数据量大的页面运行得有点慢,浏览器会变得迟钝。可以在低配置的PC客户端上清楚地看到这一点。可能会问的另一件事是,为什么不创建一个新的空表格,然后复制整个结构(包括内联样式和外部CSS)的主表格(使用window.getComputedStyle()来完成)?它会运行得更快,因为不复制整个数据量大的表格。是的,也觉得对。但不幸的是,这个提议仍然有很多未解决的问题。此外,浏览器兼容性仍然是这个提议的一个缺点。

测试用例 3:

正如上面解释的,克隆整个表格是完美的解决方案。但仍然有一个小缺点,如下所示:

热修复方法是确保所有“可见”属性(字体、边框、填充...)都已设置,不要“继承”或默认未设置。

权衡选项

解决方案

如何操作

优点

缺点

1. 分离表头行。逐个分离单元格。将它们的位置设置为“fixed”。简单且易于定制。适合简单的表格设计。在每个浏览器中都不兼容。

2. 克隆表头行。克隆一个具有与表头行相同结构的新DIV元素。解决Safari/Flock浏览器的UI问题。当表格的样式太复杂时,效果不佳。

3. 克隆整个表格。在DIV元素(最上层)中克隆整个表格,该元素与整个表头行的高度相同。确保在所有情况下都具有最高的精度和无错误。兼容除IE6之外的所有浏览器。当表格的数据量太大时,将沉重的处理负担留给客户端。

预览

上述的外观和感觉真的很吸引人,不是吗?发现它对于长数据列表特别有帮助,因为当查看时很容易失去视线。特别是第三种解决方案是“一种尺寸适合所有”的方法,几乎适用于所有浏览器。

现在让构建一个库来支持主要的UI功能。如果可以将所有上述内容打包并放入一个与UI松散耦合的实用程序函数中,那将是很好的事情。在本文中,实现了函数FreezeTableHeader()并将其放入名为“GridHelper”的类中(也应该放置在程序集中)。开发人员剩下的工作是提供参数,如gridview ID或CSS类,以及进一步的可选变量来控制冻结行为。通过这样做,主要的开发源代码是精简的。

现在,让直接跳到现场演示:

http://phamdinhtruong.7hostfree.com/FreezingTable.aspx

也可以通过动画演示预览,它演示了在垂直/水平滚动时冻结网格标题。甚至超出了这一点,网格标题可以在某个容器内停靠。在这个演示中,可以看到嵌套表格的标题在父表格的某个行内停靠。

上述解决方案帮助在浏览器窗口内以及某个预定义区域内构建了冻结表头行。特别是完整的解决方案(第三种解决方案)现在可以帮助冻结甚至“多行”标题部分(其中单元格被合并)。也可以使用相同的技术来冻结页脚行。真的很想知道这段代码是否对有帮助。请在评论中告诉对这篇文章的感觉。随时准备帮助解决任何建议/问题。

版本1.0(2012年7月20日)- 初始发布

版本2.0(2012年9月10日)- 修复Safari和Flock的问题

版本3.0(2012年9月25日)- 修复同一页面上的多个GridView和嵌套GridView的问题。

版本4.0(2012年11月7日)- 修复并微调精确冻结表头行的问题。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485