这篇文章本来在2个月前就应该写了的,只是一直没有找到好的解决方案,所以迟迟没有动笔,直到今天,才找到了比较满意的解决方案。
网上关于固定GridView表头,常见的有两种解决方案,一种是采用css样式,一种则是使用js代码。我再后面贴出了网上常用的解决方案,不过这两种解决方案都无法从根本上解决问题,并且还有一个致命的缺点,那就是在FF中不支持,我认为采用jquery重写表头扩展GridView才是釜底抽薪的解决办法。记得在网上有一个固定表头的GridView扩展控件,不过这个控件在Update下面一回发就会报错。我这个控件是在GridViewFixedHeaderExtender控件之上进行了改良的,因为我发现GridViewFixedHeaderExtender在IE9中页面第一次加载的时候表头布局会乱,经过我一番研究,发现这是因为在IE9中它的相对定位出了问题,苦思了一整天,终于想出了一个好的解决方案,在IE9中,对其进行特别处理,表头的外层设置为相对定位,内层设置为绝对定位,这样就一切oK了。
本控件最终效果图:
以下是ScrollGridView的源代码:
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Web;
using System.Security.Permissions;
[assembly: WebResource("SureKAM.SPM.Portal.Controls.Resources.Script.GridViewFixedHeaderExtender.js", "application/x-javascript", PerformSubstitution = true)]
namespace SureKAM.SPM.Portal.Controls
{
[
AspNetHostingPermission(SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal),
AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal),
Designer("SureKAM.SPM.Portal.Controls.SimpleDesigner, SureKAM.SPM.Portal.Controls"),
ToolboxData("<{0}:GridViewFixedHeaderExtender runat=server></{0}:GridViewFixedHeaderExtender>"),
TargetControlType(typeof(GridView))
]
public class GridViewFixedHeaderExtender : ExtenderControl
{
#region Overrides
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
}
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors(Control targetControl)
{
if (TargetControl == null || !TargetControl.Visible || TargetControl.Rows.Count == 0)
{
TargetControl.Height = Unit.Empty;
yield break;
}
ScriptBehaviorDescriptor descriptor = new ScriptBehaviorDescriptor("SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender", targetControl.ClientID);
descriptor.AddProperty("scrollField", HiddenFieldID);
yield return descriptor;
}
protected override IEnumerable<ScriptReference> GetScriptReferences()
{
if (TargetControl == null || !TargetControl.Visible || TargetControl.Rows.Count == 0)
{
TargetControl.Height = Unit.Empty;
yield break;
}
yield return new ScriptReference("SureKAM.SPM.Portal.Controls.Resources.Script.GridViewFixedHeaderExtender.js", this.GetType().Assembly.FullName);
}
protected override void Render(HtmlTextWriter writer)
{
ScriptManager.RegisterHiddenField(
this,
HiddenFieldID,
LastScroll.ToString()
);
base.Render(writer);
}
private GridView TargetControl
{
get
{
GridView result = this.NamingContainer.FindControl(TargetControlID) as GridView;
return result;
}
}
private int LastScroll
{
get
{
int result = 0;
if (Page.Request[HiddenFieldID] != null)
{
int.TryParse(Page.Request[HiddenFieldID], out result);
}
return result;
}
}
private string HiddenFieldID
{
get
{
return String.Format("{0}_GVFHE_Scroll", ClientID);
}
}
#endregion
}
}
js代码如下:
/// <reference name="MicrosoftAjax.debug.js" />
/// <reference name="MicrosoftAjaxTimer.debug.js" />
/// <reference name="MicrosoftAjaxWebForms.debug.js" />
Type.registerNamespace("SureKAM.SPM.Portal.Controls");
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender = function (element) {
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender.initializeBase(this, [element]);
this._documentResizeDelegate = null;
this._lock = false;
this._mainTableID = null;
this._innerTableID = null;
this._divChild = null;
this._scrollField = 0;
}
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender.prototype = {
// Overrides
//#region
initialize: function () {
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender.callBaseMethod(this, 'initialize');
this.initGrid();
},
dispose: function () {
//Add custom dispose actions here
$removeHandler(window, "resize", this._documentResizeDelegate);
if (this._divChild) {
$clearHandlers(this._divChild);
}
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender.callBaseMethod(this, 'dispose');
},
//#endregion
// Properties
//#region
get_scrollField: function () {
return this._scrollField;
},
set_scrollField: function (value) {
if (this._scrollField !== value) {
this._scrollField = value;
this.raisePropertyChanged('scrollField');
}
},
//#endregion
// Methods
//#region
getLastScroll: function () {
var result = 0;
var hf = $get(this._scrollField);
if (hf) {
result = parseInt(hf.value);
if (!result) result = 0;
}
return result;
},
setLastScroll: function (value) {
var hf = $get(this._scrollField);
if (hf) {
hf.value = value;
}
},
initGrid: function () {
// create deep clone of target grid
var target = this.get_element();
var clone = target.cloneNode(true);
// get desired height of inner scrollable area
var height = target.style.height;
var width = target.style.width;
var mainTable = target.cloneNode(false);
mainTable.style.position = "relative";
mainTable.id = String.format("outer_{0}", target.id);
target.parentNode.insertBefore(mainTable, target);
var header = target.rows[0].cloneNode(true);
if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.split(";")[1].replace(/[ ]/g, "") == "MSIE9.0") {
var headDiv = document.createElement("div");
headDiv.style.position = "relative";
headDiv.style.width = "100%";
var mainHead = document.createElement("thead");
mainHead.style.position = "absolute";
headDiv.appendChild(mainHead);
mainTable.appendChild(headDiv);
var div = document.createElement("div");
div.style.height = target.rows[0].style.height;
div.style.width = target.rows[0].style.width;
//div.style.minWidth = target.rows[0].style.width;
//div.style.position = "static";
mainTable.appendChild(div);
}
else {
var mainHead = document.createElement("thead");
mainTable.appendChild(mainHead);
}
var mainBody = document.createElement("tbody");
mainTable.appendChild(mainBody);
// Clone original header
//var header = target.rows[0].cloneNode(true);
mainHead.appendChild(header);
// add scrollable area mainTable
var secondRow = document.createElement("tr");
mainBody.appendChild(secondRow);
var mainTd = document.createElement("td");
secondRow.appendChild(mainTd)
this.setAttribute(mainTd, "colspan", target.rows[0].cells.length);
this.setAttribute(mainTd, "align", "left");
this.setAttribute(mainTd, "valign", "top");
var divChild = document.createElement("div");
mainTd.appendChild(divChild);
divChild.style.width = width;
divChild.style.height = height;
$addHandler(divChild, "scroll", Function.createDelegate(this, this.syncScroll));
divChild.style.overflow = "auto";
divChild.style.overflowX = "hidden";
divChild.style.overflowY = "scroll";
this._divChild = divChild;
// Sys.UI.DomElement.addCssClass(divChild, "divScrollVertical");
// now remove old grid from document and insert new clone into the place
target.parentNode.removeChild(target);
divChild.appendChild(clone);
// assign extender related data to clone
clone._behaviors = target._behaviors;
clone.GridViewFixedHeaderExtender = target.GridViewFixedHeaderExtender;
// correct styles
var attributes = [];
for (var i = 0; i < clone.attributes.length; i++) {
var attr = clone.attributes.item(i);
var value = attr.value.trim().toLowerCase();
if (value != "cellpadding" && value != "cellspacing") {
Array.add(attributes, attr);
}
}
Array.forEach(attributes, this.deleteAttribute, clone);
clone.deleteRow(clone.rows[0]);
clone.border = "0";
clone.style.borderWidth = "0px";
//clone.style.width = "100%";
clone.style.height = "";
mainTable.style.height = "";
target.style.height = "";
// correct widths of header columns and subscribe to document resize event:
this._mainTableID = mainTable.id;
this._innerTableID = clone.id;
this._documentResizeDelegate = Function.createDelegate(
this,
this.syncWidths
);
this._documentResizeDelegate.call();
// Attach to window's resize event to resize header cells when inner cells change their size
$addHandler(window, "resize", this._documentResizeDelegate);
// Restore scroll position from last time
divChild.scrollTop = this.getLastScroll();
},
setAttribute: function (element, attribute, value) {
var namedItem = document.createAttribute(attribute);
namedItem.value = value;
element.attributes.setNamedItem(namedItem);
},
deleteAttribute: function (attribute, index, attributes) {
this.removeAttribute(attribute);
},
syncScroll: function (args) {
if (this._divChild) {
this.setLastScroll(this._divChild.scrollTop);
}
},
syncWidths: function (args) {
if (!this._lock) {
this._lock = true;
var mainTable = $get(this._mainTableID);
var innerCellPadding = mainTable.cellPadding;
var header = mainTable.rows[0];
var innerTable = $get(this._innerTableID);
var originalRow = innerTable.rows[0];
var headerWidth = Sys.UI.DomElement.getBounds(header).width;
var originalRowWidth = Sys.UI.DomElement.getBounds(originalRow).width;
var diff = headerWidth - originalRowWidth - innerCellPadding * 2;
if (originalRow && header) {
for (var i = 0; i < originalRow.cells.length; i++) {
var bounds = Sys.UI.DomElement.getBounds(originalRow.cells[i]);
var x = bounds.width;
if (i == originalRow.cells.length - 1) {
x = x + diff - innerCellPadding * 2;
} else {
x = x - innerCellPadding;
}
if (navigator.appName == "Microsoft Internet Explorer" && navigator.appVersion.split(";")[1].replace(/[ ]/g, "") == "MSIE9.0") {
}
else {
header.cells[i].style.width = x + "px";
}
}
}
this._lock = false;
}
}
//#endregion
}
SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender.registerClass('SureKAM.SPM.Portal.Controls.GridViewFixedHeaderExtender', Sys.UI.Behavior);
1,样式固定。
这个方法是从网上参考的,但是忘记了来源,使用之后发现效果不是很好,有闪动,并且在FF浏览器中不支持。以下是源码(来源于网络):
<style type="text/css">
.Freezing
{
position:relative;
table-layout:fixed;
top:expression(this.offsetParent.scrollTop);
z-index:10;
}
.Freezing th{text-overflow:ellipsis;overflow:hidden;white-space:nowrap;padding:2px;}
</style>
2,Javascript方法。
也是网上参考,搜索应该比较多,据网友回帖说是效果很好,自己使用效果不好。以下是源码分析:
//创建表头
if(document.getElementById("gvTitle")==null)
{
vargdvList=document.getElementById("gvCommon");
vargdvHeader=gdvList.cloneNode(true);
gdvHeader.id="gvTitle";
for(i=gdvHeader.rows.length-1;
i>0;i--)
{
gdvHeader.deleteRow(i);
}
document.getElementById("divTitle").appendChild(gdvHeader);
vardiv=document.getElementById("divGvData");
vartbl=document.getElementById("divTitle");
tbl.style.position="absolute";
tbl.style.zIndex=100;
tbl.style.top=div.offsetTop;
tbl.style.left=div.offsetLeft;
}
大致做法是利用JS方法Copy出一个表头 gdvHeader 放在一个“divTitle”的DIV中。
GridView是包含在“divGvData”DIV中的,然后设置divTitle的页面位置和divGvData的一致,也就是覆盖在上面。 目前发现效果还行。有一点要注意,gdvHeader.id
= "gvTitle";要重新设置一个ID,不然删除的还是GridView的数据行。缺点:FF中不支持。
HTML中的部分代码:
<divid="divTitle"style="position:relative;
top:0; left:0; overflow:hidden; width:978px; border:0px solid red;"></div>
<divid="divGvData"runat="server"style="position:relative;
top:0px; left:0px; overflow:scroll; width:994px;height:450px;"onscroll="funGrilViewScroll(); return false;">
<asp:GridViewID="gvCommon"style="position:relative;
top:0px; left:0px;"runat="server"CssClass="gvFixd"BackColor="White"BorderColor="#999999"BorderStyle="None"BorderWidth="1px"CellPadding="3"AutoGenerateColumns="False"GridLines="Vertical"PageSize="5"AllowSorting="True"OnSorting="gvCommon_Sorting">
<FooterStyleBackColor="#CCCCCC"ForeColor="Black"/>
<RowStyleBackColor="#E7E7FF"ForeColor="Black"Font-Size="Small"/>
<HeaderStyleHorizontalAlign="Center"BackColor="#000084"BorderColor="White"BorderWidth="1px"BorderStyle="Solid"Font-Bold="True"ForeColor="White"/>
</asp:GridView>
</div>
分享到:
相关推荐
ASP.NET固定GridView表头_SuperTables
gridview固定表头 横向滚动 纵向固定,即拖动横向滚动条时,表头随着表体移动,纵向拖动滚动条时,表头不动,实践得出来的结果 我用的是VS2010,C#
用于ASP.NET平台下的GridView 表头可以固定,表身可滚动。完整的源码,可以直接在VS2008以上的版本中进行运行测试。
扩展标准ASP.NET GridView控件以在网格中添加垂直滚动条
c# gridview 滚动条固定表头 IE已测试 c# gridview 滚动条固定表头 IE已测试 c# gridview 滚动条固定表头 IE已测试
asp.net GridView自定义控件源码,美化控件。
ASP.NET控件GridView用法汇总,包括基本的操作,增加,删除,修改等。
一个翻页无刷新继承自GridView的Asp.Net自定义控件,兼容IE和火狐,使用Ajax+JSON实现翻页无刷新。
这是用vs建的一个例子,关于GridView控件和FormView控件的。
asp.net的GridView控件的技术使用 asp.net的GridView控件的技术使用 asp.net的GridView控件的技术使用 asp.net的GridView控件的技术使用 (本人保证绝对实用经典整合!!!)
14.3 固定gridview表头并增加滚动条支持 527 14.3.1 功能概述 527 14.3.2 代码实现 528 14.4 本章总结 533 第15章 自定义控件设计模式下编程汇总 534 15.1 .net框架对设计时支持 534 15.2 设计时元数据支持 ...
ASP.NET中dropdownlist和GridView控件的用法,简单易学,一看就懂.
文章: http://blog.csdn.net/yysyangyangyangshan/article/details/38807287 asp.net gridview 复杂 复合 表头
vb.net DataGridView控件用法,.net DataGridView控件用法,GridView用法
ASP.NET的GridView控件自定义模板设计实例
这个与asp.net中GridView相关的一个实例,实现GridView冻结表头和列,挺好用的。
基于asp.net2.0开发的gridview数据显示控件的使用实例,通过与后台数据库连接来实现
gridview是asp.net开发中一个很有用的控件,它的功能很强大,但是要想使用好它 还是需要多多积累的,这里把一些有用的积累传上来分享
第一部分 构建ASP.NET页面 第1章 ASP.NET Framework概览 2 1.1 ASP.NET和.NET Framework 5 1.1.1 框架类库 5 1.1.2 公共语言运行库 9 1.2 ASP.NET控件 10 1.2.1 ASP.NET控件概览 11 1.2.2 HTML控件 12 1.2.3 理解...
asp.net中GridView控件的各种操作方法,使用大全,附加数据库。包含:GridView导入导出,多层嵌套,表头表尾,分页排序,结合控件,设置属性,增除删改,主键索引...物超所值,亲情放送!~