当前位置: 首页 > 编程日记 > 正文

如何在DataGrid里面产生滚动条而不滚动题头

 作者Blog:http://blog.csdn.net/cuike519/

我们在开发的时候一定遇到,使用DataGrid的时候由于不想分页(数据没有那么多)但是又显示不在一页里面,此时我们希望在DataGrid里面出现一个滚动条,可以上下滚动DataGrid里面的数据而不用上下滚动页面,由于写本文的目的是为了说明如何实现,所以对于细节性的问题读者可以自己思考完成(比如:既要分页又要滚动等等)。为了可以滚动DataGrid我们需要一个可以让客户端的Table滚动js脚本(该js代码我是从CodeProject上面下载的),但又不能滚动Table的题头(也就是第一行)。我们都知道DataGrid在解释到客户端以后将会生成一个Table,但是这个Table是由<tr><td>组成的,我们的脚本里面是需要使用到Table的Thead和Tbody的(在大多数的客户端的应用中都要用到此功能比如:客户端的排序、以及列的托拽等等),因此我们接下来的任务就是如何为我们客户端的这个DataGrid添加<thead><tbody>了。如果你对用户的自定义控件以及ASP.NET页面的原理有所了解,我们知道控件最后都是要呈现(Render)在页面上的,因此我们可以重写这个方法来完成DataGrid的自定义呈现。听一听真的有些吓人,那么复杂的控件怎么呈现?不要着急,首先我们创建一个自定义控件如下所示:
public class PowerDataGrid : System.Web.UI.WebControls.DataGrid
    由此可以看出我们的控件是继承于DataGrid的,所以我们现在的这个控件在不用写一行代码的情况下我们的这个控件已经具有DataGrid的所有的功能。接下来我们要将我们准备的js代码内嵌到我们的控件里,好让放这个控件的页面上最终在客户端都会有这段js代码用来完成我们滚动的任务。为了完成这个工作我们要重写预呈现的方法:
 protected override void OnPreRender(System.EventArgs e) {

base.OnPreRender(e);
     
         ResourceManager manager = new ResourceManager( this.GetType() );
         ResourceSet resources = manager.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
         if( !Page.IsClientScriptBlockRegistered( "SkySword.WebControl.PowerDataGrid Library" ) ) {
               String script = resources.GetString("ScrollTable");
               this.Page.RegisterClientScriptBlock("SkySword.WebControl.PowerDataGrid Library", script );
               this.Page.RegisterStartupScript("SkySword.WebControls.PowerDataGrid Init", "<script>makeScrollableTable

('"+this.ID+"',true,'auto');</script>" );
         }
      }
    在该方法中我们访问了资源文件。哦!忘了说我们还要建立一个资源文件,用来保存我们的js代码。我们首先将资源代码中对应ScrollTable的数据(一段js脚本)注册到客户端的脚本块里。最后我们为了可以初始化,将<script>makeScrollableTable('"+this.ID+"',true,'auto');</script>段脚本注册到页面加载时开始执行(我想就应该和body里面onload的方法一样吧)。当你需要加载客户端脚本的时候使用该方法是个不错的选择。好了,客户端脚本也有了,剩下的就是处理我们的客户端DataGrid了(也就是DataGrid呈现的客户端Table)。为了可以呈现我们自己的DataGrid我们需要重写呈现方法如下所示:
protected override void Render(HtmlTextWriter output)
  {
            output.Write(this.parseMarkup());
  }
    其中调用了一个parseMarkup的函数,改函数将产生一个输出的脚本(字符串),该脚本就是一个包含thead和tbody的Table。由于此方法只是由该控件自己使用所以我们将它设置成私有的代码如下:
 private string parseMarkup(){
         // 插入THead标签和TBody标签
         StringWriter writer = new StringWriter();
         HtmlTextWriter buffer = new HtmlTextWriter(writer);
         base.Render(buffer);
         string pMarkup = writer.ToString();

// 找到第一个table标签的结尾也就是第一个>字符
         pMarkup = pMarkup.Insert(pMarkup.IndexOf(">") + ">".Length, "<thead>");
         // 将第一个tr闭区间用Thead包起来,现在第一个<thead>已经画出来了需要画
         // 它的结尾</thead>和</tbody>,同样找到第一个</tr>来插入</thead>和</tdoby>
         pMarkup = pMarkup.Insert( pMarkup.IndexOf("</tr>") + "</tr>".Length,"</thead><tbody>");
         // 在最后一个</table>的前面插入一个</tbody>就可以了。
         pMarkup = pMarkup.Replace("</table>", "</tbody></table>");
         return pMarkup;      
      }
    在这个方法中我们首先实例化了一个StringWriter的对象writer,又用该对象为参数实例了一个HtmlTextWriter对象buffer,最关键的是我们调用了基类的Render用来将buffer里面填满要输出的东西(一堆脚本就是Table,如果你是用监视器查看里面的内容就可以看到)。好了剩下的工作就是分析这个脚本了,然后我们在该脚本第一个出现<tr>的地方将这个<tr>替换成<thead>和<tr>后面的替换方法类似。最后我们将这个被我们替换和修改的Table输出到客户端,一切OK!

注意:用到StringWriter的原因就是它可以从buffer里面保存原始的字符比如:/t/n什么的。 资源文件的配置方法:首先给你的工程添加一个资源文件,名字和你的控件一样,然后在该文件中添加一下小节
      <data name="ScrollTable">
  <value><![CDATA[
  <script language = 'javascript'>
  
  var container = new Array();
var onResizeHandler;

function scrollbarWidth(){
    var w;

if (! document.body.currentStyle)   document.body.currentStyle = document.body.style;

if (document.body.currentStyle.overflowY == 'visible' || document.body.currentStyle.overflowY == 'scroll'){
        w = document.body.offsetWidth - document.body.clientLeft - document.body.clientWidth;
    }else{
        win = window.open("about:blank", "_blank", "top=0,left=0,width=100,height=100,scrollbars=yes");
        win.document.writeln('scrollbar');
        w = win.document.body.offsetWidth - win.document.body.clientLeft - win.document.body.clientWidth;
        win.close();
    }

return w;
}

function getActualWidth(e){
    if (! e.currentStyle)   e.currentStyle = e.style;

return  e.clientWidth - parseInt(e.currentStyle.paddingLeft) - parseInt(e.currentStyle.paddingRight);
}

function findRowWidth(r){
    for (var i=0; i < r.length; i++){
        r[i].actualWidth = getActualWidth(r[i]);
    }
}

function setRowWidth(r){
    for (var i=0; i < r.length; i++){
        r[i].width = r[i].actualWidth;
        r[i].innerHTML = '<span style="width:' + r[i].actualWidth + ';">' + r[i].innerHTML + '</span>';
    }
}

function fixTableWidth(tbl){
    for (var i=0; i < tbl.tHead.rows.length; i++)   findRowWidth(tbl.tHead.rows[i].cells);
    findRowWidth(tbl.tBodies[0].rows[0].cells);
    if (tbl.tFoot)  for (var i=0; i < tbl.tFoot.rows.length; i++)   findRowWidth(tbl.tFoot.rows[i].cells);

//tbl.width = '';

for (var i=0; i < tbl.tHead.rows.length; i++)   setRowWidth(tbl.tHead.rows[i].cells);
    setRowWidth(tbl.tBodies[0].rows[0].cells);
    if (tbl.tFoot)  for (var i=0; i < tbl.tFoot.rows.length; i++)   setRowWidth(tbl.tFoot.rows[i].cells);
}

function makeScrollableTable(tbl,scrollFooter,height){
    var c, pNode, hdr, ftr, wrapper, rect;

if (typeof tbl == 'string') tbl = document.getElementById(tbl);

pNode = tbl.parentNode;
    fixTableWidth(tbl);

c = container.length;
    container[c] = document.createElement('<SPAN style="height: 100; overflow: auto;">');
    container[c].id = tbl.id + "Container";
    pNode.insertBefore(container[c], tbl);
    container[c].appendChild(tbl);
    container[c].style.width = tbl.clientWidth + 2 * tbl.clientLeft + scrollbarWidth();

hdr = tbl.cloneNode(false);
    hdr.id += 'Header';
    hdr.appendChild(tbl.tHead.cloneNode(true));
    tbl.tHead.style.display = 'none';

if (!scrollFooter || !tbl.tFoot){
        ftr = document.createElement('<SPAN style="width:1;height:1;clip: rect(0 1 1 0);background-color:transparent;">');
        ftr.id = tbl.id + 'Footer';
        ftr.style.border = tbl.style.border;
        ftr.style.width = getActualWidth(tbl) + 2 * tbl.clientLeft;
        ftr.style.borderBottom = ftr.style.borderLeft = ftr.style.borderRight = 'none';
    }else{
        ftr = tbl.cloneNode(false);
        ftr.id += 'Footer';
        ftr.appendChild(tbl.tFoot.cloneNode(true));
        ftr.style.borderTop = 'none';
        tbl.tFoot.style.display = 'none';
    }

wrapper = document.createElement('<table border=0 cellspacing=0 cellpadding=0>');
    wrapper.id = tbl.id + 'Wrapper';
    pNode.insertBefore(wrapper, container[c]);

wrapper.insertRow(0).insertCell(0).appendChild(hdr);
    wrapper.insertRow(1).insertCell(0).appendChild(container[c]);
    wrapper.insertRow(2).insertCell(0).appendChild(ftr);

wrapper.align = tbl.align;
    tbl.align = hdr.align = ftr.align = 'left';
    hdr.style.borderBottom = 'none';
    tbl.style.borderTop = tbl.style.borderBottom = 'none';

// adjust page size
    if (c == 0 && height == 'auto'){
        onResizeAdjustTable();
        onResizeHandler = window.onresize;
        window.onresize = onResizeAdjustTable;
    }else{
        container[c].style.height = height;
    }
}

function onResizeAdjustTable(){
    if (onResizeHandler) onResizeHandler();

var rect = container[0].getClientRects()(0);
    var h = document.body.clientHeight - (rect.top + (document.body.scrollHeight - rect.bottom));
    container[0].style.height = (h > 0) ? h : 1;
}

function printPage(){
    var tbs = document.getElementsByTagName('TABLE');
    var e;

for (var i=0; i < container.length; i++)    container[i].style.overflow = '';

window.print();

for (var i=0; i < container.length; i++)    container[i].style.overflow = 'auto';
}
  
 </script> 
  ]]></value>
 </data>
  
    好了,这样就可以完成了。使用该方法可以实现客户端的排序和托拽功能,只要你找到相应的js代码(或者自己写)然后使用此法分析你的客户端代码,最后将你的DataGrid的输出定位成你想要的结果,一切就OK了!由于时间关系该控件分页和滚动不能同时,希望有兴趣的网友可以实现之。我在写此文章的目的旨在抛砖引玉的作用,希望对大家的编程技术有所提高和帮助。谢谢阅读!有什么问题或者好的建议请与我联系。

相关文章:

“小霸王学习机”再现?树莓派400正式发布,售价70美元

整理 | 高卫华出品 | AI科技大本营头图 | CSDN 下载自视觉中国11月2日&#xff0c;树莓派 4 的制造商正式推出了树莓派 400&#xff0c;这是一款集成了 4GB 内存树莓派 4 的紧凑型键盘。有了树莓派 400&#xff0c;只需使用其两个微型HDMI端口之一&#xff0c;将其插入电视或显…

display的block、none、inline属性及解释

常会用到display对应值有block、none、inline这三个值 参数&#xff1a; block :块对象的默认值。用该值为对象之后添加新行。之前也添加一行。 none :隐藏对象。与visibility属性的hidden值不同&#xff0c;其不为被隐藏的对象保留其物理空间 inline :内联对象的默认值。用该值…

datagrid分页问题(前后跳页)《控件版》

在ASCX中写的。 在CSDN上看了很多的DATAGRID分页问题&#xff0c;当然DATAGRID有自己的分页项&#xff0c;功能是很有限的&#xff0c;我也在CSDN上看了很多自己分页的代码&#xff0c;发现都是用C#写的&#xff0c;我写了一个用ASP。NET中VB语言写的。以下代码供大家参考。 HT…

F5第一个10000台

F5中国第一个累积销售10000台&#xff0c;花了整整9年时间。下一个累积销售10000台需要多少时间&#xff0c;5年&#xff0c;3年&#xff0c;甚至更短的时间&#xff1f;让我们拭目以待。转载于:https://blog.51cto.com/f5555/1126095

java内存溢出的情况解决方法

内存溢出虽然很棘手&#xff0c;但也有相应的解决办法&#xff0c;可以按照从易到难&#xff0c;一步步的解决。  第一步&#xff0c;就是修改JVM启动参数&#xff0c;直接增加内存。这一点看上去似乎很简单&#xff0c;但很容易被忽略。JVM默认可以使用的内存为64M&#xff…

DataGrid基于Access的快速分页法

DataGrid基于Access的快速分页法撰文/ 黎波DataGrid是一个功能非常强大的ASP.NET Web服务器端控件&#xff0c;它除了能够方便地按各种方式格式化显示表格中的数据&#xff0c;还可以对表格中的数据进行动态的排序、编辑和分页。使Web开发人员从繁琐的代码中解放。实现DataGrid…

urlrewrite使用小结

urlrewrite顾名思义&#xff0c;就是对URL进行重写&#xff0c;用户得到的全部都是经过处理后的URL地址&#xff0c;这样做我觉得好处有三&#xff1a;一&#xff1a;提高安全性&#xff0c;可以有效的避免一些参数名、ID等完全暴露在用户面前&#xff0c;如果用户随便乱输的话…

性能超越图神经网络,将标签传递和简单模型结合实现SOTA

译者 | 刘畅出品 | AI科技大本营头图 | CSDN付费下载自视觉中国图神经网络&#xff08;GNNs&#xff09;是图学习中一种主流的技术。然而&#xff0c;对于GNN为什么在实际使用中很成功以及它们是否是优异性能所必需的技术&#xff0c;了解相对较少。本文展示了许多标准的传导节…

模仿VIMD的模式的简化代码示例

按numpad0来切换模式&#xff0c;按t显示不同的结果&#xff1b; Numpad0:: tfmode:!tfmode aaa:(tfmode1?"AAAA":"BBBB") SplashImage Off SplashImage, "",X500 Y500 W200 B fs10 CT00FFFF CW000000,%aaa%, , 切换模式提示 WinSet, Tr…

DataGrid连接Access的快速分页法(1)——需求与现状

作者&#xff1a;黎波一、需求分析 DataGrid是一个功能强大的ASP.NET Web服务器端控件&#xff0c;它除了能够按各种方式格式化显示数据&#xff0c;还可以对数据进行动态的排序、编辑和分页。大大减轻了广大Web程序员的工作量。实现DataGrid的分页功能一直是很多入门者感到棘手…

CSDN公众号新功能上线,居然还能搜出小姐姐???

为了给各位打工人更好的搜索体验CSDN总是在学习新技能这次CSDN公众号又给大家带来了一项全新的搜索技能在CSDN旗下的公众号内回复消息就能自动回复想搜索的内容啦小编来给大家演示一下&#xff0c;在公众号内输入“mysql安装教程”&#xff0c;就能得到CSDN全站内关于mysql安装…

p2v、v2v 转换-windows篇

问题&#xff1a;如何把 xenserver的虚拟机转成Esxi的虚拟机 如何把物理机转成Esxi的虚拟机答案&#xff1a;↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓首先介绍一下实验环境。一台xenserver主机上两台虚拟机 win03和win08 转到Esxi5.0的一台主机上。Esxi5.0在某个…

WebViewJavascriptBridge原理解析

基本说明 我们的项目是一个OC与javascript重度交互的app&#xff0c;OC与javascript交互的那部分是在WebViewJavascriptBridge的github地址的基础上修改的&#xff0c;WebViewJavascriptBridge应该是当前最流行最成功的OC与Web交互实现了。最近看了一下他的实现原理&#xff0c…

DataGrid连接Access的快速分页法(2)——SQL语句的选用(升序与降序)

作者&#xff1a;黎波 一、相关概念 在 ACCESS 数据库中&#xff0c;一个表的主键&#xff08;PRIMARY KEY&#xff0c;又称主索引&#xff09;上必然建立了唯一索引&#xff08;UNIQUE INDEX&#xff09;&#xff0c;因此主键字段的值是不会重复的。并且索引页依据索引列的值…

从谷歌AutoML到百度EasyDL,AI大生产时代,调参师不再是刚需

出品 | AI科技大本营头图 | 付费下载于视觉中国2018 年&#xff0c;Google Cloud 宣布将 AutoML 作为机器学习产品的一部分。至此&#xff0c;AutoML 开始进入大众的视野。 实际上&#xff0c;2013 年AutoWEKA的发布可以算作AutoML的开端&#xff1b;2014 年&#xff0c;ICML开…

Python 语法小知识

为什么80%的码农都做不了架构师&#xff1f;>>> 序列解包 将含有多个值的序列解开&#xff0c;然后把值存放到变量中&#xff0c;当函数或者方法返回元组时这个特性很有用&#xff0c;可以把返回的序列值直接赋值给变量&#xff0c;在序列解包时等号两边的元素个数…

CSS布局之-水平垂直居中

对一个元素水平垂直居中&#xff0c;在我们的工作中是会经常遇到的&#xff0c;也是CSS布局中很重要的一部分&#xff0c;本文就来讲讲CSS水平垂直居中的一些方法。另外&#xff0c;文中的css都是用less书写的&#xff0c;如果看不懂less&#xff0c;可以把我给的demo链接打开&…

DataGrid连接Access的快速分页法——动态生成SQL语句

作者&#xff1a;黎波using System;using System.Text;namespace Paging{/// <summary>/// FastPaging 的摘要说明。/// </summary>public class FastPaging {private FastPaging() {}/// <summary>/// 获取根据指定字段排序并分页查询的 SELECT 语句。/// &…

一文读懂机器学习“数据中毒”

作者 | Ben Dickson翻译 | 火火酱~出品 | AI科技大本营头图 | 付费下载于视觉中国在人类的眼中&#xff0c;下面的三张图片分别展示了三样不同的东西&#xff1a;一只鸟、一只狗和一匹马。但对于机器学习算法来说&#xff0c;这三者或许表示同样的东西:一个有黑边的白色小方框。…

chartee

2019独角兽企业重金招聘Python工程师标准>>> 一个绘制图表的类库&#xff0c;支持绘制股票的K线图&#xff0c;还可以绘制曲线、柱状图等等。 Code4App编译测试&#xff0c;测试环境&#xff1a;Xcode 4.3, iOS 5.0。 转载:http://www.adobex.com/ios/source/detail…

C语言存储类关键字

1、static这个关键字有三种用法&#xff1a;&#xff08;1&#xff09;第一种是用来修饰局部变量&#xff0c;使之成为静态局部变量&#xff1b;静态局部变量存储在数据段/bss段中&#xff0c;作用域是代码块作用域&#xff0c;生命周期是程序生命周期&#xff0c;链接属性是无…

显示DataGrid序号的一个适用的方法

作者Blog&#xff1a;http://blog.csdn.net/wangj2001/如果数据量小的话没有问题&#xff0c;一旦数据量大&#xff0c;显示特别慢&#xff0c;还有个缺点就是拖动行高时行号不随行高的变化而变动&#xff0c;出现是几个序号在一个单元格中显示。我自己对他们的算法进行总结&am…

Integer的自动缓存

2019独角兽企业重金招聘Python工程师标准>>> Interger装箱有个自动缓存的概念 Integer a 100;Integer b 100;Integer c 200;Integer d 200;System.out.println(a b); //trueSystem.out.println(c d); //false Integer是对象&#xff0c;比较的是对象在内存中…

崩溃!双十一第 4 天,某互联网公司黄了?

01打折这么狠是不是要黄了&#xff1f;&#xff1f;今年的双十一&#xff0c;开始地比以往早一些&#xff01;不知道各位程序员小哥哥们的战绩如何&#xff0c;是不是已经被一轮又一轮的定金、尾款&#xff0c;折腾到数学细胞耗尽&#xff1f;付款了也不清楚自己有没有真正的「…

FreeBSD设备驱动管理介绍(BSP: Ti AM335x)

这段时间一直在忙FreeBSD驱动移植的项目&#xff0c;因此对FreeBSD做了一定的了解&#xff0c;鉴于网上对于FreeBSD的设备驱动资料较少&#xff0c;在这里给出本人对于FreeBSD驱动管理的理解心得&#xff08;主要是USB驱动管理&#xff09;&#xff0c;希望能对开源开发者有所帮…

视障人士体验自动驾驶:携导盲犬登车,未来有望“自己开”

6月27日&#xff0c;滴滴出行首次面向公众开放自动驾驶服务。用户可通过滴滴APP线上报名&#xff0c;审核通过后&#xff0c;将能在上海自动驾驶测试路段&#xff0c;免费呼叫自动驾驶车辆进行试乘体验。现阶段&#xff0c;滴滴自动驾驶载人测试范围仅限于在上海开放测试道路上…

Listview获取选中行的值

一般情况请注意别先删除了选中行&#xff0c;又去使用。那就会导致找不到选中行。。。。。哥犯了这个错误。。。找了很长时间问题if (this.lstwlview.SelectedIndices.Count > 0) { if (MessageBox.Show("确认删除该条码&#xff1f;",…

asp.net中DataGrid性能测试

作者Blog&#xff1a;http://blog.csdn.net/yzdy/ 测试环境&#xff1a;数据库服务器:2.4G P4 CPU&#xff0c;2G 内存&#xff0c;Windows Advanced Server 2000&#xff0c;SQL Server 2000Web服务器&#xff1a;2.4G P4 CPU&#xff0c;1G 内存&#xff0c;Windows Advanced…

javassist学习笔记

2019独角兽企业重金招聘Python工程师标准>>> 介绍&#xff1a;www.javassist.org/ javassist、ASM 对比 1、javassist是基于源码级别的API比基于字节码的ASM简单。 2、基于javassist开发&#xff0c;不需要了解字节码的一些知识&#xff0c;而且其封装的一些工具类可…