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

一、概述

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

二、实现方案

为了实现该效果图,在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,完成

时间: 2012-10-12

解析asp.net的分页控件

一.说明 AspNetPager.dll这个分页控件主要用于asp.net webform网站,现将整理代码如下 二.代码 1.首先在测试页面Default.aspx页面添加引用 <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix="webdiyer" %> 2.写一个Repeater列表控件用于显示数据 <asp:Repeater ID

分享一个asp.net pager分页控件

效果: js: 复制代码 代码如下: $.fn.extend({ JPager: function (cfg, pageIndex, pageSize) { if (cfg && pageIndex > 0 && pageSize>0) { var token = "#" + this.attr("id"); this.empty(); var pageFirst = function () { $(token).JPag

asp.net自定义分页控件示例

一..ascx页面 复制代码 代码如下: <%@ Control Language="C#" AutoEventWireup="true" CodeBehind="Pagination.ascx.cs" Inherits="IOCS.WEB.UserControl.Pagination" %><link href="../Content/Css/Pager.css" rel="s

asp.net webform自定义分页控件

做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: <style type="text/css"> .pager-m-l { margin-left: 10px; } .pager { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; fo

asp.net web页面自定义分页控件使用详解

这几天学习了一下自定义分页控件,现将实现方法记录下来,亲测可以实现: 1.首先创建一个.ascx文件,命名为TurnPage,然后在里面写控件前台展示的界面: 2.然后在TurnPage.ascx.cs里面写相应的后台代码,代码如下: namespace Web { public delegate void GoToPage(int PageNum); public partial class TurnPage : System.Web.UI.UserControl { private GoTo

asp.net分页控件AspNetPager的样式美化

在前段时间的开发网站的过程中,突然觉得这个简洁的样式看着和网站整体的风格实在不搭调,于是看看AspNetPager的最后生成html,写了一段CSS样式,将分页的样式和网站整体风格统一起来了. 效果如下: 做的不是很好看,希望大家不要丢砖头,俺的头没包棉絮,伤不起 ~-_-~ CSS样式表: /* AspNetPager Style Power By http://www.edweb.cn */.pager{ width:95%;  margin:10px; line-height:20px;

AspNetAjaxPager,Asp.Net通用无刷新Ajax分页控件,支持多样式多数据绑定

本控件可以对GridView,Repeater,DataGrid,DataList...几乎所有的.net数据绑定控件进行分页,全部无刷新,数据绑定部分可以使用存储过程也可以直接使用sql语句,这对本控件没有任何干扰!本控件具有较好的用户界面,能够根据需要变换各种样式,配合css控制效果则更好! 1.分页样式效果图: 2.如何使用: 于bin目录下添加:AspNetAjaxPager.dll引用 aspx文件内容: 复制代码 代码如下: <%@ Page Language="C#"

asp.net分页控件使用详解【附实例下载】

一.说明 AspNetPager.dll这个分页控件主要用于asp.net webform网站,现将整理代码如下 二.代码 1.首先在测试页面Default.aspx页面添加引用 <%@ Register Assembly="AspNetPager" Namespace="Wuqi.Webdiyer" TagPrefix="webdiyer" %> 2.写一个Repeater列表控件用于显示数据 <asp:Repeater ID

asp.net下Repeater使用 AspNetPager分页控件

一.AspNetPager分页控件 分页是Web应用程序中最常用到的功能之一,在ASP.NET中,虽然自带了一个可以分页的DataGrid(asp.net 1.1)和GridView(asp.net 2.0)控件,但其分页功能并不尽如人意,如可定制性差.无法通过Url实现分页功能等,而且有时候我们需要对DataList和Repeater甚至自定义数据绑定控件进行分页,手工编写分页代码不但技术难度大.任务繁琐而且代码重用率极低,因此分页已成为许多ASP.NET程序员最头疼的问题之一. AspNet

关于asp.net 自定义分页控件

这几天空学习了下自定义控件,参考了aspnetpager开发了自己的分页控件.相对aspnetpager来说功能是多,但个人感觉他的代码太多. 界面: 使用: <%@ Register assembly="YSM.AspNetPager" namespace="YSM.AspNetPager" tagprefix="cc1" %> 页面注册控件,也可以在web.config中配置 1.ajax之UpdatePanel分页则把控件放到U

ASP.NET MVC分页控件

1.下载MvcPager.dll文件并引用到MVC项目中 2.在控制器中引用命名空间using Webdiyer.WebControls.Mvc; 3.获取数据集合,数据的总记录数(数据集合有多少条数据),设置每页记录数多少(每页显示多少条数据),获取当前页码(当前第几页) 例如: 4.创建视图,将换成 5.在web.config中的 6.在显示的数据下面 @Html.Pager(Model, new PagerOptions() { AlwaysShowFirstLastPageNumber

asp.net 使用ObjectDataSource控件在ASP.NET中实现Ajax真分页

ListView控件本身并没有分页功能,不过借助于ASP.NET中新增加的DataPager控件,我们可以非常方便地对ListView中的数据设置分页,这几乎不需要开发人员写一行代码,将ListView控件放到页面上,设置好布局和DataSource,然后再添加一个DataPager控件,将它的PagedControlID属性设置成ListView的ID,PageSize中设置每页要显示的数据条数,然后在Fields中设置好分页的样式(当然你完全可以不用去管样式,ASP.NET会根据内置的样式来