如何在DataGrid里面产生滚动条而不滚动题头
我們?cè)陂_(kāi)發(fā)的時(shí)候一定遇到,使用DataGrid的時(shí)候由于不想分頁(yè)(數(shù)據(jù)沒(méi)有那么多)但是又顯示不在一頁(yè)里面,此時(shí)我們希望在DataGrid里面出現(xiàn)一個(gè)滾動(dòng)條,可以上下滾動(dòng)DataGrid里面的數(shù)據(jù)而不用上下滾動(dòng)頁(yè)面,由于寫(xiě)本文的目的是為了說(shuō)明如何實(shí)現(xiàn),所以對(duì)于細(xì)節(jié)性的問(wèn)題讀者可以自己思考完成(比如:既要分頁(yè)又要滾動(dòng)等等)。為了可以滾動(dòng)DataGrid我們需要一個(gè)可以讓客戶(hù)端的Table滾動(dòng)js腳本(該js代碼我是從CodeProject上面下載的),但又不能滾動(dòng)Table的題頭(也就是第一行)。我們都知道DataGrid在解釋到客戶(hù)端以后將會(huì)生成一個(gè)Table,但是這個(gè)Table是由<tr><td>組成的,我們的腳本里面是需要使用到Table的Thead和Tbody的(在大多數(shù)的客戶(hù)端的應(yīng)用中都要用到此功能比如:客戶(hù)端的排序、以及列的托拽等等),因此我們接下來(lái)的任務(wù)就是如何為我們客戶(hù)端的這個(gè)DataGrid添加<thead><tbody>了。如果你對(duì)用戶(hù)的自定義控件以及ASP.NET頁(yè)面的原理有所了解,我們知道控件最后都是要呈現(xiàn)(Render)在頁(yè)面上的,因此我們可以重寫(xiě)這個(gè)方法來(lái)完成DataGrid的自定義呈現(xiàn)。聽(tīng)一聽(tīng)真的有些嚇人,那么復(fù)雜的控件怎么呈現(xiàn)?不要著急,首先我們創(chuàng)建一個(gè)自定義控件如下所示:
public class PowerDataGrid : System.Web.UI.WebControls.DataGrid
??? 由此可以看出我們的控件是繼承于DataGrid的,所以我們現(xiàn)在的這個(gè)控件在不用寫(xiě)一行代碼的情況下我們的這個(gè)控件已經(jīng)具有DataGrid的所有的功能。接下來(lái)我們要將我們準(zhǔn)備的js代碼內(nèi)嵌到我們的控件里,好讓放這個(gè)控件的頁(yè)面上最終在客戶(hù)端都會(huì)有這段js代碼用來(lái)完成我們滾動(dòng)的任務(wù)。為了完成這個(gè)工作我們要重寫(xiě)預(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>" );
???????? }
????? }
??? 在該方法中我們?cè)L問(wèn)了資源文件。哦!忘了說(shuō)我們還要建立一個(gè)資源文件,用來(lái)保存我們的js代碼。我們首先將資源代碼中對(duì)應(yīng)ScrollTable的數(shù)據(jù)(一段js腳本)注冊(cè)到客戶(hù)端的腳本塊里。最后我們?yōu)榱丝梢猿跏蓟?#xff0c;將<script>makeScrollableTable('"+this.ID+"',true,'auto');</script>段腳本注冊(cè)到頁(yè)面加載時(shí)開(kāi)始執(zhí)行(我想就應(yīng)該和body里面onload的方法一樣吧)。當(dāng)你需要加載客戶(hù)端腳本的時(shí)候使用該方法是個(gè)不錯(cuò)的選擇。好了,客戶(hù)端腳本也有了,剩下的就是處理我們的客戶(hù)端DataGrid了(也就是DataGrid呈現(xiàn)的客戶(hù)端Table)。為了可以呈現(xiàn)我們自己的DataGrid我們需要重寫(xiě)呈現(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包起來(lái),現(xiàn)在第一個(gè)<thead>已經(jīng)畫(huà)出來(lái)了需要畫(huà)
???????? // 它的結(jié)尾</thead>和</tbody>,同樣找到第一個(gè)</tr>來(lái)插入</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的對(duì)象writer,又用該對(duì)象為參數(shù)實(shí)例了一個(gè)HtmlTextWriter對(duì)象buffer,最關(guān)鍵的是我們調(diào)用了基類(lèi)的Render用來(lái)將buffer里面填滿要輸出的東西(一堆腳本就是Table,如果你是用監(jiān)視器查看里面的內(nèi)容就可以看到)。好了剩下的工作就是分析這個(gè)腳本了,然后我們?cè)谠撃_本第一個(gè)出現(xiàn)<tr>的地方將這個(gè)<tr>替換成<thead>和<tr>后面的替換方法類(lèi)似。最后我們將這個(gè)被我們替換和修改的Table輸出到客戶(hù)端,一切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)客戶(hù)端的排序和托拽功能,只要你找到相應(yīng)的js代碼(或者自己寫(xiě))然后使用此法分析你的客戶(hù)端代碼,最后將你的DataGrid的輸出定位成你想要的結(jié)果,一切就OK了!由于時(shí)間關(guān)系該控件分頁(yè)和滾動(dòng)不能同時(shí),希望有興趣的網(wǎng)友可以實(shí)現(xiàn)之。我在寫(xiě)此文章的目的旨在拋磚引玉的作用,希望對(duì)大家的編程技術(shù)有所提高和幫助。謝謝閱讀!有什么問(wèn)題或者好的建議請(qǐng)與我聯(lián)系。
總結(jié)
以上是生活随笔為你收集整理的如何在DataGrid里面产生滚动条而不滚动题头的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: DataGrid删除确认及Item颜色交
- 下一篇: datagrid分页问题(前后跳页)《控