使用 JavaScript 和 CSS 冻结 ASP.NET GridView 标题






4.55/5 (13投票s)
使用 JavaScript 和 CSS 冻结 ASP.NET GridView 标题。
引言
如今,对于 Web 开发人员来说,冻结 ASP.NET GridView
标题是一个常见的需求。出于可用性的考虑,对于像 DataGrid
、GridView
或原始 HTML 表格等数据查看控件,冻结或固定标题是必不可少的。您可能已经注意到,在 Excel 中,您可以冻结电子表格的标题单元格。当您向下滚动时,标题始终可见,使您的表格更易于阅读。通常需要在 GridView
控件中实现相同的效果,尤其是在一次显示许多记录时。 在本文中,我将解释一种可以轻松实现此效果的技术。
概念讨论
我们都知道,在执行服务器端代码后,原始 HTML 会返回到浏览器,浏览器只是显示 HTML。显然,GridView
需要转换为 HTML 表格。因此,我们需要对返回的表格进行一些自定义才能达到我们的目标。以下是一些执行该自定义的步骤:
- 移除通常表示标题的表格行,并将其分配给新创建的“
<THEAD>
”标签。 - 通过限制表格的高度并添加“
overflow: auto
”属性到“<TBODY>
”和“<DIV>
”内部,使表格/网格的其余行可滚动。“<DIV>
”只是网格上方的包装器,有助于表示可滚动的选项。 - 现在,使用适用于浏览器的技术(因为不同的浏览器在这种情况下表现不同)固定/冻结“
<THEAD>
”。
现在,无论您滚动网格行,标题始终保持在顶部行。
Using the Code
完整的示例代码如下所示。您还可以从上面的链接下载示例项目。
<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<style type="text/css">
.WrapperDiv
{
width:560px;height:290px;border: 1px solid black;
}
.WrapperDiv TH
{
/* Needed for IE */
position: relative;
}
.WrapperDiv TR
{
/* Needed for IE */
height:0px;
}
.ScrollContent
{
/* Needed for Opera */
display: block;
overflow: auto;
width: 100%;
height: 250px;
}
.FixedHeader
{
/* Needed for opera */
display: block;
}
</style>
<script runat="server">
ICollection CreateDataSource( )
{
System.Data.DataTable dt = new System.Data.DataTable();
System.Data.DataRow dr;
dt.Columns.Add(new System.Data.DataColumn("Product Id", typeof(System.String)));
dt.Columns.Add(new System.Data.DataColumn("Product Name", typeof(System.String)));
dt.Columns.Add(new System.Data.DataColumn("Product Price", typeof(System.Decimal)));
dt.Columns.Add(new System.Data.DataColumn("Manufacture Time", typeof(System.String)));
dt.Columns.Add(new System.Data.DataColumn("Expired Time", typeof(System.String)));
for (int i = 1; i <= 50; i++)
{
System.Random rd = new System.Random(Environment.TickCount * i); ;
dr = dt.NewRow();
dr[0] = i.ToString();
dr[1] = "Sample Product" + i.ToString();
dr[2] = System.Math.Round(rd.NextDouble() * 100, 2);
dr[3] = "September/2008";
dr[4] = "September/2012";
dt.Rows.Add(dr);
}
System.Data.DataView dv = new System.Data.DataView(dt);
return dv;
}
protected void Page_Load( object sender, EventArgs e )
{
if (!IsPostBack)
{
GridView1.DataSource = CreateDataSource();
GridView1.DataBind();
}
}
</script>
<script type="text/ecmascript">
var headerHeight = 8;
/// <summary>
/// Responsible for call appropriate function according to browser
/// for Browser Compatibility
/// </summary>
function onLoad()
{
if(navigator.appName == "Opera")
{
freezeGridViewHeaderForOpera('GridView1');
}
else
{
freezeGridViewHeaderForIEAndFF('GridView1','WrapperDiv');
}
}
/// <summary>
/// Used to create a fixed GridView header and allow scrolling
/// for IE and FF (Tested in IE-7 and FF-3.0.3)
/// </summary>
/// <param name="gridViewId" type="String">
/// Client-side ID of the GridView control
/// </param>
/// <param name="wrapperDivCssClass" type="String">
/// CSS class to be applied to the GridView's wrapper div element.
/// </param>
function freezeGridViewHeaderForIEAndFF(gridViewId,wrapperDivCssClass)
{
var grid = document.getElementById(gridViewId);
if (grid != 'undefined')
{
grid.style.visibility = 'hidden';
var div = null;
if (grid.parentNode != 'undefined')
{
//Find wrapper div output by GridView
div = grid.parentNode;
if (div.tagName == "DIV")
{
div.className = wrapperDivCssClass;
div.style.overflow = "auto";
}
}
var grid = prepareFixedHeader(grid);
var tbody = grid.getElementsByTagName('TBODY')[0];
//Needed for Firefox
tbody.style.height = (div.offsetHeight - headerHeight) + 'px';
tbody.style.overflowX = "hidden";
tbody.overflow = 'auto';
tbody.overflowX = 'hidden';
grid.style.visibility = 'visible';
}
}
/// <summary>
/// Used to create a fixed GridView header and allow scrolling
/// for Opera (Tested in Opera-9.2)
/// </summary>
/// <param name="gridViewId" type="String">
/// Client-side ID of the GridView control
/// </param>
function freezeGridViewHeaderForOpera(gridViewId)
{
var grid = document.getElementById(gridViewId);
if (grid != 'undefined')
{
grid = prepareFixedHeader(grid);
var headers = grid.getElementsByTagName('THEAD')[0];
headers.className = "FixedHeader";
var tbody = grid.getElementsByTagName('TBODY')[0];
tbody.className = "ScrollContent";
var cells = tbody.childNodes[0];
for(var i = 0; i < cells.childNodes.length;i++)
{
var tableCell = cells.childNodes[i];
var tableCellWidth = getStyle(tableCell,'width')
var headerCell = headers.childNodes[0].childNodes[i];
var headerCellWidth = getStyle(headerCell,'width');
if(widthPxToInt(tableCellWidth) > widthPxToInt(headerCellWidth))
{
headerCell.style.width=(widthPxToInt(tableCellWidth) - 10) + "px";
}
else
{
tableCell.style.width=(widthPxToInt(headerCellWidth) - 10) + "px";
}
}
}
}
/// <summary>
/// Used to prepare a fixed GridView header
/// </summary>
/// <param name="grid" type="GridView">
/// The Reference Of GridView control
/// </param>
function prepareFixedHeader(grid)
{
//Find DOM TBODY element and and
var tags = grid.getElementsByTagName('TBODY');
if (tags != 'undefined')
{
var tbody = tags[0];
var trs = tbody.getElementsByTagName('TR');
if (trs != 'undefined')
{
headerHeight += trs[0].offsetHeight;
//Remove first TR tag from it
var headTR = tbody.removeChild(trs[0]);
//create a new element called THEAD
var head = document.createElement('THEAD');
head.appendChild(headTR);
//add to a THEAD element instead of TR so CSS styles
//can be applied properly in both IE and FireFox
grid.insertBefore(head, grid.firstChild);
}
}
return grid;
}
function getStyle(oElm, strCssRule)
{
var strValue = "";
if(document.defaultView && document.defaultView.getComputedStyle){
strValue = document.defaultView.getComputedStyle(oElm,
"").getPropertyValue(strCssRule);
}
else if(oElm.currentStyle){
strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
return p1.toUpperCase();
});
strValue = oElm.currentStyle[strCssRule];
}
return strValue;
}
/// <summary>
/// Used to convert from Pxel to Integer
/// </summary>
/// <param name="width" type="String">
/// Width of any thing like GridHeader,GridCell
/// </param>
function widthPxToInt(width)
{
width = width.substr(0,width.length-2);
return new Number(width);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:GridView ID="GridView1" runat="server"
Font-Size="12px" BackColor="#FFFFFF"
GridLines="Both" CellPadding="4" Width="560px">
<HeaderStyle BackColor="#EDEDED" Height="26px" />
</asp:GridView>
</div>
</form>
</body>
</html>
<script type="text/ecmascript">
window.onload = onLoad();
</script>
浏览器兼容性
由于我使用了 JavaScript 和 CSS 来解决此问题,因此毫无疑问会引发“此解决方案是否与所有浏览器兼容?”的问题。如果您在 Google 上搜索,您会找到许多针对此问题的解决方案。但我尚未找到支持所有浏览器的客户端解决方案。大多数解决方案支持 Firefox 和 IE。但很少支持 Opera。
我在 FireFox-3.0.3、IE-7 和 Opera-9.2 中测试了提供的解决方案,并获得了成功的结果。