王朝网络
分享
 
 
 

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

王朝other·作者佚名  2006-01-30
宽屏版  字体: |||超大  

我们在开发的时候一定遇到,使用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>

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有