我们在开发的时候一定遇到,使用DataGrid的时候由于不想分页(数据没有那么多)但是又显示不在一页里面,此时我们希望在DataGrid里面出现一个滚动条,可以上下滚动DataGrid里面的数据而不用上下滚动页面,由于写本文的目的是为了说明如何实现,所以对于细节性的问题读者可以自己思考完成(比如:既要分页又要滚动等等)。为了可以滚动DataGrid我们需要一个可以让客户端的Table滚动js脚本(该js代码我是从CodeProject上面下载的),但又不能滚动Table的题头(也就是第一行)。我们都知道DataGrid在解释到客户端以后将会生成一个Table,但是这个Table是由
|
|
组成的,我们的脚本里面是需要使用到Table的Thead和Tbody的(在大多数的客户端的应用中都要用到此功能比如:客户端的排序、以及列的托拽等等),因此我们接下来的任务就是如何为我们客户端的这个DataGrid添加
了。如果你对用户的自定义控件以及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", " makeScrollableTable
('"+this.ID+"',true,'auto');" );
}
}
在该方法中我们访问了资源文件。哦!忘了说我们还要建立一个资源文件,用来保存我们的js代码。我们首先将资源代码中对应ScrollTable的数据(一段js脚本)注册到客户端的脚本块里。最后我们为了可以初始化,将 makeScrollableTable('"+this.ID+"',true,'auto');段脚本注册到页面加载时开始执行(我想就应该和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, "
");
// 将第一个tr闭区间用Thead包起来,现在第一个
已经画出来了需要画
// 它的结尾和,同样找到第一个来插入和
pMarkup = pMarkup.Insert( pMarkup.IndexOf("") + "".Length,"
");
// 在最后一个的前面插入一个就可以了。
pMarkup = pMarkup.Replace("", "");
return pMarkup;
}
在这个方法中我们首先实例化了一个StringWriter的对象writer,又用该对象为参数实例了一个HtmlTextWriter对象buffer,最关键的是我们调用了基类的Render用来将buffer里面填满要输出的东西(一堆脚本就是Table,如果你是用监视器查看里面的内容就可以看到)。好了剩下的工作就是分析这个脚本了,然后我们在该脚本第一个出现
的地方将这个
替换成
和
后面的替换方法类似。最后我们将这个被我们替换和修改的Table输出到客户端,一切OK!
注意:用到StringWriter的原因就是它可以从buffer里面保存原始的字符比如:/t/n什么的。资源文件的配置方法:首先给你的工程添加一个资源文件,名字和你的控件一样,然后在该文件中添加一下小节
<data name="ScrollTable"></data>
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>
分享到:
相关推荐
WPF 中在datagrid中使用滚动条显示所有数据。 初学,欢迎交流。 下载次数越多所需积分越高,不定期改低积分。
2.0DataGrid嵌套DataGrid,里面的鼠标滚动响应到外部,利用自定义命令传递滚轮事件参数实现,详细效果请移步: https://blog.csdn.net/u010438205/article/details/105710794
1、分页控件DataPager的简单使用。 2、可以控制外置的ScrollBar来实现对指定DataGrid的滚动操作。
有的时候,会遇到DataGrid里面嵌套DataGrid(重叠嵌套),然后里面的鼠标滚轮无法响应外面的滚动,为此记录下解决方案,详情请移步:https://blog.csdn.net/u010438205/article/details/105659330
asp.net 中 datagrid 标题跟内容列对齐
自定义DataGrid的列标题样式,行样式,鼠标悬浮及选择样式。 自定义滚动条样式,包括箭头及滚动区。
在WPF中,如果DataGrid里使用了模板列,当拖动滚动条时,往往会出现列表内容显示混乱的情况。解决方法就是在Binding的时候给UpdateSourceTrigger赋值。 <RowDefinition Height=25></RowDefinition> ...
DataGrid 底部合计,在DataGrid 的外部,底部横向滚动条的下面做的汇总。
DataGrid鼠标滚动 基于msflexgrid功能改良扩展示例----商业日报和私人旅行里程
gridview固定表头 横向滚动 纵向固定,即拖动横向滚动条时,表头随着表体移动,纵向拖动滚动条时,表头不动,实践得出来的结果 我用的是VS2010,C#
easyui的datagrid生成合并行,合计计算价格!
怎样使DataGrid支持鼠标滚轮滚动记录-精品源代码
WPF中DataGrid里面的Checkbox实现单选关键代码, 文档里面的代码复制粘贴即可实现!本人也是项目需要写的一个功能11行代码实现此功能! 希望可以帮助到你们!
自己写的一个小例子,关于实现datagrid逐行显示的例子,类似于滚动新闻。粗糙
DataGrid 统计每一列的值,合计在底部。 这里的合计是在 DataGrid 的内部,汇总在最后一行,在 DataGrid 横向滚动条的上方进行汇总。
jquery easy ui datagrid完整项目源代码,非常值得学习
项目中用到DataGrid, 需要在第一列添加checkbox, 可以多选、全选。 其中涉及的概念DataTemplate, DataGridCellStyle, DataGridCellControlTemplate,Binding, OnPropertyChanged等。
本列子不使用ToolKit(有3.5和4.0的限制),添加一个类,重写DataGrid。可以在DataGrid上下左右绑定一个DataGrid,类似Footer属性。示例可直接运行,简单易懂。 (思路:两个DataGrid(mainDG,bottomDG),bottomDG...
datagrid设行背景色示例,提供了继承好的datagrid子类,