如何在DataGrid里面產(chǎn)生滾動(dòng)條
2024-07-21 02:23:13
供稿:網(wǎng)友
我們在開發(fā)的時(shí)候一定遇到使用datagrid的時(shí)候由于不想分頁(數(shù)據(jù)沒有那么多)但是又顯示不在一頁里面,此時(shí)我們希望在datagrid里面出現(xiàn)一個(gè)滾動(dòng)條,可以上下滾動(dòng)datagrid里面的數(shù)據(jù)而不用上下滾動(dòng)頁面,由于寫本文的目的是為了說明如何實(shí)現(xiàn),所以對于細(xì)節(jié)性的問題讀者可以自己思考完成(比如:既要分頁又要滾動(dòng)等等)。為了可以滾動(dòng)datagrid我們需要一個(gè)可以讓客戶端的table滾動(dòng)js腳本(該js代碼我是從codeproject上面下載的),但又不能滾動(dòng)table的題頭(也就是第一行)。我們都知道datagrid在解釋到客戶端以后將會(huì)生成一個(gè)table,但是這個(gè)table是由<tr><td>組成的,我們的腳本里面是需要使用到table的thead和tbody的(在大多數(shù)的客戶端的應(yīng)用中都要用到此功能比如:客戶端的排序、以及列的托拽等等),因此我們接下來的任務(wù)就是如何為我們客戶端的這個(gè)datagrid添加<thead><tbody>了。如果你對用戶的自定義控件以及asp.net頁面的原理有所了解,我們知道控件最后都是要呈現(xiàn)(render)在頁面上的,因此我們可以重寫這個(gè)方法來完成datagrid的自定義呈現(xiàn)。聽一聽真的有些嚇人,那么復(fù)雜的控件怎么呈現(xiàn)?不要著急,首先我們創(chuàng)建一個(gè)自定義控件如下所示:public class powerdatagrid : system.web.ui.webcontrols.datagrid
由此可以看出我們的控件是繼承于datagrid的,所以我們現(xiàn)在的這個(gè)控件在不用寫一行代碼的情況下我們的這個(gè)控件已經(jīng)具有datagrid的所有的功能。接下來我們要將我們準(zhǔn)備的js代碼內(nèi)嵌到我們的控件里,好讓放這個(gè)控件的頁面上最終在客戶端都會(huì)有這段js代碼用來完成我們滾動(dòng)的任務(wù)。為了完成這個(gè)工作我們要重寫預(yù)呈現(xiàn)的方法:
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>" );
}
}
在該方法中我們訪問了資源文件。哦!忘了說我們還要建立一個(gè)資源文件,用來保存我們的js代碼。我們首先將資源代碼中對應(yīng)scrolltable的數(shù)據(jù)(一段js腳本)注冊到客戶端的腳本塊里。最后我們?yōu)榱丝梢猿跏蓟瑢?lt;script>makescrollabletable('" + this.id + "',true,'auto');</script>段腳本注冊到頁面加載時(shí)開始執(zhí)行(我想就應(yīng)該和body里面onload的方法一樣吧)。當(dāng)你需要加載客戶端腳本的時(shí)候使用該方法是個(gè)不錯(cuò)的選擇。好了,客戶端腳本也有了,剩下的就是處理我們的客戶端datagrid了(也就是datagrid呈現(xiàn)的客戶端table)。為了可以呈現(xiàn)我們自己的datagrid我們需要重寫呈現(xiàn)方法如下所示:
protected override void render(htmltextwriter output)
{
output.write(this.parsemarkup());
}
其中調(diào)用了一個(gè)parsemarkup的函數(shù),改函數(shù)將產(chǎn)生一個(gè)輸出的腳本(字符串),該腳本就是一個(gè)包含thead和tbody的table。由于此方法只是由該控件自己使用所以我們將它設(shè)置成私有的代碼如下:
private string parsemarkup(){
// 插入thead標(biāo)簽和tbody標(biāo)簽
stringwriter writer = new stringwriter();
htmltextwriter buffer = new htmltextwriter(writer);
base.render(buffer);
string pmarkup = writer.tostring();
// 找到第一個(gè)table標(biāo)簽的結(jié)尾也就是第一個(gè)>字符
pmarkup = pmarkup.insert(pmarkup.indexof(">") + ">".length, "<thead>");
// 將第一個(gè)tr閉區(qū)間用thead包起來,現(xiàn)在第一個(gè)<thead>已經(jīng)畫出來了需要畫
// 它的結(jié)尾</thead>和</tbody>,同樣找到第一個(gè)</tr>來插入</thead>和</tdoby>
pmarkup = pmarkup.insert( pmarkup.indexof("</tr>") + "</tr>".length,"</thead><tbody>");
// 在最后一個(gè)</table>的前面插入一個(gè)</tbody>就可以了。
pmarkup = pmarkup.replace("</table>", "</tbody></table>");
return pmarkup;
}
在這個(gè)方法中我們首先實(shí)例化了一個(gè)stringwriter的對象writer,又用該對象為參數(shù)實(shí)例了一個(gè)htmltextwriter對象buffer,最關(guān)鍵的是我們調(diào)用了基類的render用來將buffer里面填滿要輸出的東西(一堆腳本就是table,如果你是用監(jiān)視器查看里面的內(nèi)容就可以看到)。好了剩下的工作就是分析這個(gè)腳本了,然后我們在該腳本第一個(gè)出現(xiàn)<tr>的地方將這個(gè)<tr>替換成<thead>和<tr>后面的替換方法類似。最后我們將這個(gè)被我們替換和修改的table輸出到客戶端,一切ok!
注意:用到stringwriter的原因就是它可以從buffer里面保存原始的字符比如:/t/n什么的。 資源文件的配置方法:首先給你的工程添加一個(gè)資源文件,名字和你的控件一樣,然后在該文件中添加一下小節(jié)
<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>
好了,這樣就可以完成了。使用該方法可以實(shí)現(xiàn)客戶端的排序和托拽功能,只要你找到相應(yīng)的js代碼(或者自己寫)然后使用此法分析你的客戶端代碼,最后將你的datagrid的輸出定位成你想要的結(jié)果,一切就ok了!由于時(shí)間關(guān)系該控件分頁和滾動(dòng)不能同時(shí),希望有興趣的網(wǎng)友可以實(shí)現(xiàn)之。我在寫此文章的目的旨在拋磚引玉的作用,希望對大家的編程技術(shù)有所提高和幫助。謝謝閱讀!有什么問題或者好的建議請與我聯(lián)系。