欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

asp.net中使用自定义控件的方式实现一个分页控件的代码

程序员文章站 2024-03-31 19:20:46
一、概述 在web开发中,常常需要显示一些数据,而为了方便排版及浏览,我们只需要显示所有记录中的一部分。一般情况下,我们采用分页来实现这个需求。实现分页的方法多种多样,在本...
一、概述

在web开发中,常常需要显示一些数据,而为了方便排版及浏览,我们只需要显示所有记录中的一部分。一般情况下,我们采用分页来实现这个需求。实现分页的方法多种多样,在本文中,我们采用了一个分页空间来记录记录总数、当前页、总页数及页面大小等。为了有一个直观上的印象,先展示该控件运行后的效果,效果如下图所示:

asp.net中使用自定义控件的方式实现一个分页控件的代码


二、实现方案

为了实现该效果图,在asp.net中,可以使用custom controls and user controls两种方式,user controls的实现方式及其简单,而且使用起来和平时使用controls的方式差别极大,所以我们采用custom controls实现。
参考资料:professional asp.net 2.0 server control and component development

三、分页控件的实现

1)、新建一个asp.net server control项目,
2)、在该项目中添加一个asp.net server control的item,并设置其name为pageon,
3)、修改该类继承于compositecontrol类,并修改其attribute为如下所示:

复制代码 代码如下:

[defaultproperty("pagesize")]
[toolboxdata("<{0}:pageon runat=server width=100%></{0}:pageon>")]
public class pageon : compositecontrol

注:自定义控件必须继承自control或者其子类。
4)、 定义需要被组合的控件
复制代码 代码如下:

label lblmessage;
linkbutton btnfirst;
linkbutton btnprev;
linkbutton btnnext;
linkbutton btnlast;
textbox txtgopage;
button btngo;

5)、定义分页控件需要用到的proptery
分页控件主要包括页面大小、当前页、总记录数及总页数等属性,并需要保存在viewstate中,详细代码如下所示:
复制代码 代码如下:

public int rowcount
{
get
{
if (viewstate["m_rowcount"] == null || int.parse(viewstate["m_rowcount"].tostring()) < 0)
{
viewstate["m_rowcount"] = 0;
}
return int.parse(viewstate["m_rowcount"].tostring());
}
set
{
if (value < 0)
{
viewstate["m_rowcount"] = 0;
}
else
{
viewstate["m_rowcount"] = value;
}
this.recreatechildcontrols();
}
}
public int curpage
{
get
{
if (viewstate["m_curpage"] ==null || int.parse(viewstate["m_curpage"].tostring()) < 1)
{
viewstate["m_curpage"] = 1;
}
return int.parse(viewstate["m_curpage"].tostring());
}
set
{
if (value < 1)
{
viewstate["m_curpage"] = 1;
}
else if (value > pagecount)
{
viewstate["m_curpage"] = pagecount;
}
else
{
viewstate["m_curpage"] = value;
}
}
}
public int pagecount
{
get
{
return rowcount / pagesize + 1;
}
}
public int pagesize
{
get
{
if (viewstate["m_pagesize"] ==null || int.parse(viewstate["m_pagesize"].tostring()) < 1)
{
viewstate["m_pagesize"] = 15;
}
return int.parse(viewstate["m_pagesize"].tostring());
}
set
{
if (value > 0)
{
viewstate["m_pagesize"] = value;
this.recreatechildcontrols();
}
}
}

6)、生成自定义控件的子空间
生成自定义空间的子空间需要override基类control中的createchildcontrols()方法,详细代码如下所示:
复制代码 代码如下:

protected override void createchildcontrols()
{
controls.clear();
lblmessage = new label();
lblmessage.text = "当前第" + curpage + "页 共" + pagecount + "页  共" + rowcount + "条记录";
lblmessage.id = "lblmessage";
controls.add(lblmessage);
btnfirst = new linkbutton();
btnfirst.text = "首页";
btnfirst.commandname = "first";
btnfirst.id = "btnfirst";
if (curpage <= 1)
{
btnfirst.enabled = false;
}
controls.add(btnfirst);
btnprev = new linkbutton();
btnprev.text = "上一页";
btnprev.commandname = "prev";
btnprev.id = "btnprev";
if (curpage <= 1)
{
btnprev.enabled = false;
}
controls.add(btnprev);
btnnext = new linkbutton();
btnnext.text = "下一页";
btnnext.commandname = "next";
btnnext.id = "btnnext";
if (curpage >= pagecount)
{
btnnext.enabled = false;
}
controls.add(btnnext);
btnlast = new linkbutton();
btnlast.text = "末页";
btnlast.commandname = "last";
btnlast.id = "btnlast";
if (curpage >= pagecount)
{
btnlast.enabled = false;
}
controls.add(btnlast);
txtgopage = new textbox();
txtgopage.tabindex = 1;
txtgopage.id = "txtgopage";
txtgopage.attributes.add("onkeyup", @"this.value=this.value.replace(/\d/g,'')");
txtgopage.attributes.add("onafterpaste", @"this.value=this.value.replace(/\d/g,'')");
controls.add(txtgopage);
btngo = new button();
btngo.tabindex = 2;
btngo.commandname = "go";
btngo.text = "go";
btngo.id="btngo";
controls.add(btngo);
debug.writeline("ffffffffffffffffffffffffffffffffffffffffffffffffff");
base.createchildcontrols();
}

7)、定义自定义控件的布局
第6步完成后,所有定义的控件都会顺序显示到页面上了,但是这样的效果不友好,如果对于多行的空间更是如此,所有我们需要定义控件的布局,自定义控件的布局需要重写rendercontents()方法及tagkey属性,此示例中的代码如下所示:
复制代码 代码如下:

protected override void rendercontents(htmltextwriter output)
{
output.renderbegintag(htmltextwritertag.tr);
output.addstyleattribute("text-align", "left");
output.renderbegintag(htmltextwritertag.td);
output.write("  ");
lblmessage.rendercontrol(output);
output.renderendtag();
output.addstyleattribute("text-align", "right");
output.renderbegintag(htmltextwritertag.td);
btnfirst.rendercontrol(output);
output.write("  ");
btnprev.rendercontrol(output);
output.write("  ");
btnnext.rendercontrol(output);
output.write("  ");
btnlast.rendercontrol(output);
output.write("到");
output.addstyleattribute(htmltextwriterstyle.width, "30px");
txtgopage.rendercontrol(output);
output.write("页");
btngo.rendercontrol(output);
output.write("  ");
output.renderendtag();
output.renderendtag();
}
protected override htmltextwritertag tagkey
{
get
{
return htmltextwritertag.table;
}
}

上面的代码中,我们使用table来布局,也可以使用其它的布局方式,比如div+css。
8)、捕捉并处理控件的事件
到此以后,这些代码已经可以生成文章开头图所显示的效果,但是什么事情也做不了,不能响应该控件上的事件,所有还需要继续实现该控件上的事件代码,实现这些事件采用冒泡所有子控件的事件来实现。
首先,定义一个委托:
复制代码 代码如下:

public delegate void pageoneventhandler(object sender, eventargs args);

其次,定义基于该委托的事件:
复制代码 代码如下:

public event pageoneventhandler recpagechanged;

最后,重写冒泡事件,并根据参数特征,捕获需要处理的事件,使其调用需要的方法。
复制代码 代码如下:

protected override bool onbubbleevent(object source, eventargs args)
{
bool handled = false;
commandeventargs cea = args as commandeventargs;
if(cea == null)
{
return handled;
}
switch (cea.commandname)
{
case "first":
handled = true;
curpage = 1;
break;
case "prev":
handled = true;
if (curpage > 1)
{
curpage--;
}
else
{
curpage = 1;
}
break;
case "next":
handled = true;
if (curpage < pagecount)
{
curpage ++ ;
}
else
{
curpage = pagecount;
}
break;
case "last":
handled = true;
curpage = pagecount;
break;
case "go":
string strgo = txtgopage.text.trim();
int igo;
if (!string.isnullorempty(strgo) && int.tryparse(strgo, out igo))
{
handled = true;
curpage = igo;
}
break;
}
if (handled)
{
if (this.recpagechanged != null)
{
recpagechanged(this, args);
this.recreatechildcontrols();
}
return handled;
}
else
{
return base.onbubbleevent(source, args);
}
}

到此就完成了分页控件的开发。
注:可以定制该控件的样式,或者使用属性暴露子控件的属性来控制样式等.
四、使用分页控件
完成自定义控件的开发后,在toolbox中choose items或者直接在需要使用该自定义控件的项目中引用该项目或者dll,即可在toolbox中显示自定义控件了。然后用拖拽的方式即可把分页控件放到需要的地方,就像使用button控件一样简单。
然后再该页面的后台代码的onload事件中,注册需要被调用的方法到该控件的recpagechanged事件中,如下所示:
复制代码 代码如下:

pageon1.recpagechanged += new customcontrol.pageoneventhandler(pageon1_recpagechanged);

最后,只需要在方法pageon1_recpagechanged中编写自己的代码即可。
复制代码 代码如下:

void pageon1_recpagechanged(object sender, eventargs args)
{
//to do something
}

控件的详细代码如下:
复制代码 代码如下:

namespace customcontrol
{
public delegate void pageoneventhandler(object sender, eventargs args);
[defaultproperty("pagesize")]
[toolboxdata("<{0}:pageon runat=server width=100%></{0}:pageon>")]
public class pageon :compositecontrol
{
#region
label lblmessage;
linkbutton btnfirst;
linkbutton btnprev;
linkbutton btnnext;
linkbutton btnlast;
textbox txtgopage;
button btngo;
#endregion
protected override void createchildcontrols()
{
controls.clear();
lblmessage = new label();
lblmessage.text = "当前第" + curpage + "页 共" + pagecount + "页  共" + rowcount + "条记录";
lblmessage.id = "lblmessage";
controls.add(lblmessage);
btnfirst = new linkbutton();
btnfirst.text = "首页";
btnfirst.commandname = "first";
btnfirst.id = "btnfirst";
if (curpage <= 1)
{
btnfirst.enabled = false;
}
controls.add(btnfirst);
btnprev = new linkbutton();
btnprev.text = "上一页";
btnprev.commandname = "prev";
btnprev.id = "btnprev";
if (curpage <= 1)
{
btnprev.enabled = false;
}
controls.add(btnprev);
btnnext = new linkbutton();
btnnext.text = "下一页";
btnnext.commandname = "next";
btnnext.id = "btnnext";
if (curpage >= pagecount)
{
btnnext.enabled = false;
}
controls.add(btnnext);
btnlast = new linkbutton();
btnlast.text = "末页";
btnlast.commandname = "last";
btnlast.id = "btnlast";
if (curpage >= pagecount)
{
btnlast.enabled = false;
}
controls.add(btnlast);
txtgopage = new textbox();
txtgopage.tabindex = 1;
txtgopage.id = "txtgopage";
txtgopage.attributes.add("onkeyup", @"this.value=this.value.replace(/\d/g,'')");
txtgopage.attributes.add("onafterpaste", @"this.value=this.value.replace(/\d/g,'')");
controls.add(txtgopage);
btngo = new button();
btngo.tabindex = 2;
btngo.commandname = "go";
btngo.text = "go";
btngo.id="btngo";
controls.add(btngo);
debug.writeline("ffffffffffffffffffffffffffffffffffffffffffffffffff");
base.createchildcontrols();
}
public int rowcount
{
get
{
if (viewstate["m_rowcount"] == null || int.parse(viewstate["m_rowcount"].tostring()) < 0)
{
viewstate["m_rowcount"] = 0;
}
return int.parse(viewstate["m_rowcount"].tostring());
}
set
{
if (value < 0)
{
viewstate["m_rowcount"] = 0;
}
else
{
viewstate["m_rowcount"] = value;
}
this.recreatechildcontrols();
}
}
public int curpage
{
get
{
if (viewstate["m_curpage"] ==null || int.parse(viewstate["m_curpage"].tostring()) < 1)
{
viewstate["m_curpage"] = 1;
}
return int.parse(viewstate["m_curpage"].tostring());
}
set
{
if (value < 1)
{
viewstate["m_curpage"] = 1;
}
else if (value > pagecount)
{
viewstate["m_curpage"] = pagecount;
}
else
{
viewstate["m_curpage"] = value;
}
}
}
public int pagecount
{
get
{
return rowcount / pagesize + 1;
}
}
public int pagesize
{
get
{
if (viewstate["m_pagesize"] ==null || int.parse(viewstate["m_pagesize"].tostring()) < 1)
{
viewstate["m_pagesize"] = 15;
}
return int.parse(viewstate["m_pagesize"].tostring());
}
set
{
if (value > 0)
{
viewstate["m_pagesize"] = value;
this.recreatechildcontrols();
}
}
}
protected override void rendercontents(htmltextwriter output)
{
output.renderbegintag(htmltextwritertag.tr);
output.addstyleattribute("text-align", "left");
output.renderbegintag(htmltextwritertag.td);
output.write("  ");
lblmessage.rendercontrol(output);
output.renderendtag();
output.addstyleattribute("text-align", "right");
output.renderbegintag(htmltextwritertag.td);
btnfirst.rendercontrol(output);
output.write("  ");
btnprev.rendercontrol(output);
output.write("  ");
btnnext.rendercontrol(output);
output.write("  ");
btnlast.rendercontrol(output);
output.write("到");
output.addstyleattribute(htmltextwriterstyle.width, "30px");
txtgopage.rendercontrol(output);
output.write("页");
btngo.rendercontrol(output);
output.write("  ");
output.renderendtag();
output.renderendtag();
}
protected override htmltextwritertag tagkey
{
get
{
return htmltextwritertag.table;
}
}
public event pageoneventhandler recpagechanged;
protected override bool onbubbleevent(object source, eventargs args)
{
bool handled = false;
commandeventargs cea = args as commandeventargs;
if(cea == null)
{
return handled;
}
switch (cea.commandname)
{
case "first":
handled = true;
curpage = 1;
break;
case "prev":
handled = true;
if (curpage > 1)
{
curpage--;
}
else
{
curpage = 1;
}
break;
case "next":
handled = true;
if (curpage < pagecount)
{
curpage ++ ;
}
else
{
curpage = pagecount;
}
break;
case "last":
handled = true;
curpage = pagecount;
break;
case "go":
string strgo = txtgopage.text.trim();
int igo;
if (!string.isnullorempty(strgo) && int.tryparse(strgo, out igo))
{
handled = true;
curpage = igo;
}
break;
}
if (handled)
{
if (this.recpagechanged != null)
{
recpagechanged(this, args);
this.recreatechildcontrols();
}
return handled;
}
else
{
return base.onbubbleevent(source, args);
}
}
}
}

ok,完成