作者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了!由于时间关系该控件分页和滚动不能同时,希望有兴趣的网友可以实现之。我在写此文章的目的旨在抛砖引玉的作用,希望对大家的编程技术有所提高和帮助。谢谢阅读!有什么问题或者好的建议请与我联系。

如何在DataGrid里面产生滚动条而不滚动题头相关推荐

  1. 如何在DataGrid里面使用动态图形表示数字

    作者: cuike519的专栏   http://blog.csdn.net/cuike519/ 本文将要简单的介绍如何在DataGrid里面用图形表是一个数字,听起来好象要用到GUI的编程,其实不然 ...

  2. datagridview滚动条自动滚动_Win32编程基础之滚动条

    (图片来源:游戏<ATRI> 通过使用滚动条,窗口可以显示比它大的文档或图片,用户可以滚动用户区中的数据对象来看到对象超出窗口边界的部分. 如果窗口的用户区比窗口的边框要大,窗口应该使用滚 ...

  3. php如何监听页面滚动,html5中在元素滚动条在滚动时触发的事件onscroll

    实例 元素滚动时执行 JavaScript 定义和用法 onscroll 事件在元素滚动条在滚动时触发. 提示: 使用 CSS overflow 样式属性来创建元素的滚动条. 浏览器支持 语法 HTM ...

  4. 网页滚动条上下滚动固定元素左右不固定之sticky

    网页滚动条上下滚动固定元素左右不固定之sticky 有时候我们需要网页中某元素在上下滚动时可以固定在某一位置,但是左右不固定,也就是会随着左右滚动条滚动.那么我们可以通过 sticky 布局来解决. ...

  5. 两table水平滚动条级联滚动(同步滚动)。 table1放标题,table2放内容。

    //table1=head和table2=body水平滚动条级联滚动 $(document).ready(function () { $("#bodyPanel").scroll( ...

  6. DOM初探(14)——查看滚动条的滚动距离

    一:DOM基本操作: 查看滚动条的滚动距离 window.pageXOffset/pageYOffset IE8及以下不兼容(只有IE9以上的浏览器能用) document.body/document ...

  7. Javascript设置滚动条向上滚动的方法;JS设置滚动条滚动的代码

    很久就没有碰前端的后果就是,自己被公司叫来帮忙自己结果啥都会,但是就想不起怎么操作 画布哆嗦 咱们直接来看代码 重点一:获取滚动条Y轴的数据 这个方法有很多,我就不一一讲述了,毕竟结果都一样就好 直接 ...

  8. element-ui table表格 增加合计行 和 表格列固定之后 滚动条无法滚动

    element-ui table表格 增加合计行 和 表格列固定之后 滚动条无法滚动 是因为el-table__fixed或el-table__fixed-right有了合计之后把 el-table_ ...

  9. HTML滚动条平滑移动,孟欣 - JS缓冲效果,平滑移动(滚动条平滑滚动)

    JS缓冲效果,平滑移动(滚动条平滑滚动) 举个栗子: 点击导航栏的锚点,改变scroll的位置.(页面不是瞬间闪到,有个缓冲的效果) 点击button,页面瞬间闪到目标位置,这个功能很简单,不再啰嗦 ...

最新文章

  1. 线程关键字、锁、同步集合笔记
  2. DNS自述:我是如何为域名找到家的
  3. python快速编程入门教程-终于懂得python快速编程入门教程
  4. rabbitmq的基本使用
  5. 解决Nginx出现403 forbidden (13: Permission denied)报错的四种方法
  6. oracle 中的常用exception
  7. 【51nod-1289】大鱼吃小鱼
  8. 电子计算机应由,计算机
  9. Code First 迁移,及迁移错误
  10. linux驱动访问内存,linux驱动笔记八(内存与IO访问)
  11. python pickle模块详解
  12. OSPF —— 重分发(配置命令)
  13. latex生成pdf中文标签乱码pdf复制乱码
  14. 什么是 Google Play服务
  15. apue第三版P106:ftw程序中使用的path_alloc
  16. BLE中的Service(服务)和characteristic(特征值)
  17. 对HANA的认识与相关测试案例
  18. 【自考】马克思主义基本原理概论—容易混淆的点
  19. 分布式之数据库和缓存双写一致性方案解析
  20. 用python让excel飞起来(第7章 图表操作)

热门文章

  1. 【C++】多线程互斥锁、条件变量
  2. 回顾2021,展望2022
  3. C++中的.hpp理解
  4. C语言实现大数运算(长整数的加、减、乘、除)
  5. JAVA Web项目中所出现错误及解决方式合集(不断更新中)
  6. js array 删除指定元素_数组--学习笔记(数据结构数组 /js数组)
  7. 状态估计问题学习记录(1)
  8. 剑指offer:面试题29. 顺时针打印矩阵
  9. 遗传算法与C++实现
  10. 【冷知识】获取网页所有的监听事件类型、方法。请认准getEventListeners