ASP.NET控件开发之ScrollGridView(兼容FF、IE、苹果、谷歌、搜狗,固定表头滚动的GridView控件)
来源:互联网 发布:mac os固件验证错误 编辑:程序博客网 时间:2024/05/23 12:10
这篇文章本来在2个月前就应该写了的,只是一直没有找到好的解决方案,所以迟迟没有动笔,直到今天,才找到了比较满意的解决方案。
网上关于固定GridView表头,常见的有两种解决方案,一种是采用css样式,一种则是使用js代码。我再后面贴出了网上常用的解决方案,不过这两种解决方案都无法从根本上解决问题,并且还有一个致命的缺点,那就是在FF中不支持,我认为采用jquery重写表头扩展GridView才是釜底抽薪的解决办法。记得在网上有一个固定表头的GridView扩展控件,不过这个控件在Update下面一回发就会报错。我这个控件是在GridViewFixedHeaderExtender控件之上进行了改良的,因为我发现GridViewFixedHeaderExtender在IE9中页面第一次加载的时候表头布局会乱,经过我一番研究,发现这是因为在IE9中它的相对定位出了问题,苦思了一整天,终于想出了一个好的解决方案,在IE9中,对其进行特别处理,表头的外层设置为相对定位,内层设置为绝对定位,这样就一切oK了。
本控件最终效果图:
以下是ScrollGridView的源代码:
<span style="color:#00ff;">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 }}</span>
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)
{
var gdvList = document.getElementById("gvCommon");
var gdvHeader = gdvList.cloneNode(true);
gdvHeader.id = "gvTitle";
for(i = gdvHeader.rows.length - 1; i > 0;i--)
{
gdvHeader.deleteRow(i);
}
document.getElementById("divTitle").appendChild(gdvHeader);
var div = document.getElementById("divGvData");
var tbl = 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中的部分代码:
<div id="divGvData" runat="server" style="position:relative; top:0px; left:0px; overflow:scroll; width:994px;height:450px;" onscroll="funGrilViewScroll(); return false;">
<asp:GridView ID="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" >
<FooterStyle BackColor="#CCCCCC" ForeColor="Black" />
<RowStyle BackColor="#E7E7FF" ForeColor="Black" Font-Size="Small" />
<HeaderStyle HorizontalAlign="Center" BackColor="#000084" BorderColor="White" BorderWidth="1px" BorderStyle="Solid" Font-Bold="True" ForeColor="White"/>
</asp:GridView>
</div>
- ASP.NET控件开发之ScrollGridView(兼容FF、IE、苹果、谷歌、搜狗,固定表头滚动的GridView控件)
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- Asp.net 2.0 自定义控件开发[实现GridView多行表头固定表体滚动效果][示例代码下载]
- linux学习笔记(三):用root身份改了/usr/bin权限怎么办?
- ncurses简介及其使用方法
- ubuntu 软件包
- MongoDB & Redis资料汇总
- mp4文件格式解析,为demux准备的代码
- ASP.NET控件开发之ScrollGridView(兼容FF、IE、苹果、谷歌、搜狗,固定表头滚动的GridView控件)
- 磁盘配额
- Oracle获取最晚的记录
- 做一个快乐的.net程序员(很不错,推荐给大家)
- 一种新的instrumentation框架
- js正则表达式大全 --不断更新中
- Blocks编程要点[中文完整翻译版]- Blocks Programming Topics
- 使用社区OBS编译xbmc(for mer)
- Java桌面应用安装部署、安装程序制作(exe4j + Inno Setup)——之一:综述