去年就发表过asp.net 分页-利用后台直接生成html分页 ,那种方法只是单纯的实现了分页,基本不能使用,那时就想写个自己的分页控件,无奈能力有限。最近有点时间了,就自己做出了这个分页控件。我承认,这个控件参考了别人的,但是其实里面的原理都相同,差异只是展现方式而已。
去年就在做一个自己的后台系统,刚开始用的asp.net,做了一部分就没有做了,因为缺少权限控制类别。后面转为用asp.net mvc4做,也只是做了一部分,觉得不太方便,也许是我不太会用。再用ajax+ashx做了一部分,虽然体验不错,但是我还是放弃了,比起纯正的asp.net还是麻烦多了。我要做的系统不是很大,觉得用asp.net很方便,权限控制,通用控件可以加快步伐。所以我决定先做出来再说,怎么简单怎么做。
展示效果
属性解释:
Css:定义div和链接等的样式
SelectCss:当前选择的链接样式
CssEnable:本来想做一个默认的样式,但是感觉需要不大,所以这个属性暂时无用
PageSize:每页显示的数据条数
PreNextVisable:上一页和下一页的显示,默认为显示
TotalVisable:显示总数,默认为不显示,图上显示错误:共{0}笔
运行效果:
实现过程
//**************************************************************************************** //作者:轻狂书生 //博客地址:http://www.cnblogs.com/xiaoshuai1992 //create: 2014/5/5 //功能:分页控件的实现 //使用方法:正常控件使用方法 //***************************************************************************************** using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.ComponentModel; [assembly: TagPrefix("XS.Framework.Control", "xs")] namespace pageControl { public class PageChangedEventArgs : EventArgs { int ITotalCount = 0; int ICurrentPage = 0; int IPageSize = 0; public int ECurrentPage { get { return ICurrentPage; } set { ICurrentPage = value; } } public int ETotalCount { get { return ITotalCount; } set { ITotalCount = value; } } public int EPageSize { get { return IPageSize; } set { IPageSize = value; } } public PageChangedEventArgs(int curPage, int totalcount, int pageSize) { ECurrentPage = curPage; ETotalCount = totalcount; EPageSize = pageSize; } } public delegate void PageChangedEvent(object sender, PageChangedEventArgs e); public class xsPageControl : Control, IPostBackEventHandler { #region 属性 string _preText = "上一页"; string _nextText = "下一页"; string _totalText = "共{0}笔"; bool _totalVisable = false;//由于存在尾页号,总页数不是必须,故这里我设置默认为不打开 bool _preNextVisable = true; int _pageSize = 10; string _css = "xsPage"; string _selectCss = "xsSelect"; bool _cssEnable = true; int ITotalCount = 0; int ICurrentPage = 0; [Category("Text")] public string PreText { get { return _preText; } set { _preText = value; } } [Category("Text")] public string NextText { get { return _nextText; } set { _nextText = value; } } [Category("Text")] public string TotalText { get { return _totalText; } set { _totalText = value; } } [Category("Text")] public bool TotalVisable { get { return _totalVisable; } set { _totalVisable = value; } } [Category("Text")] public bool PreNextVisable { get { return _preNextVisable; } set { _preNextVisable = value; } } [Category("Size")] public int PageSize { get { return _pageSize; } set { _pageSize = value; } } [Category("CSS")] public string Css { get { return _css; } set { _css = value; } } [Category("CSS")] public string SelectCss { get { return _selectCss; } set { _selectCss = value; } } [Category("CSS")] /// <summary> /// 是否使用默认CSS,自定义CSS无效 /// </summary> public bool CssEnable { get { return _cssEnable; } set { _cssEnable = value; } } [Browsable(false)] public int CurrentPage { set { ICurrentPage = value; } } [Browsable(false)] public int TotalPage { get { int tpage = 0; if (PageSize > 0) { tpage = (TotalCount % PageSize == 0 ? TotalCount / PageSize : TotalCount / PageSize + 1); } return tpage; } } [Browsable(false)] public int TotalCount { get { return ITotalCount; } set { ITotalCount = value; } } #endregion public event PageChangedEvent PageChanged; #region 效果呈现 public override void RenderControl(HtmlTextWriter writer) { Render(writer); } protected override void Render(HtmlTextWriter writer) { if (DesignMode) { writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID); writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); writer.AddAttribute(HtmlTextWriterAttribute.Class, Css); writer.RenderBeginTag(HtmlTextWriterTag.Div); if (TotalVisable) { writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write(string.Format(TotalText, 0)); writer.RenderEndTag(); writer.Write(" "); } if (PreNextVisable) { writer.AddAttribute(HtmlTextWriterAttribute.Href, "#"); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(PreText); writer.RenderEndTag(); writer.Write(" "); } for (int i = 1; i <= 5; i++) { writer.AddAttribute(HtmlTextWriterAttribute.Href, "#"); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(i.ToString()); writer.RenderEndTag(); writer.Write(" "); } if (PreNextVisable) { writer.AddAttribute(HtmlTextWriterAttribute.Href, "#"); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(NextText); writer.RenderEndTag(); writer.Write(" "); } writer.RenderEndTag(); } else { writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID); writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); writer.AddAttribute(HtmlTextWriterAttribute.Class, Css); writer.RenderBeginTag(HtmlTextWriterTag.Div); if (TotalVisable) { writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write(string.Format(TotalText, ITotalCount)); writer.RenderEndTag(); } if (PreNextVisable && ICurrentPage != 1) { writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, ICurrentPage - 1 + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(PreText); writer.RenderEndTag(); } if (TotalPage <= 10) { for (int i = 1; i <= TotalPage; i++) { if (i == ICurrentPage) { //添加当前选择的样式 writer.AddAttribute(HtmlTextWriterAttribute.Class, SelectCss); } writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, i + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(i.ToString()); writer.RenderEndTag(); } } else { if (ICurrentPage - 5 > 2 && ICurrentPage + 7 < TotalPage)//前后都有的 { //添加第一页 writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, 1 + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write("1"); writer.RenderEndTag(); writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write("…"); writer.RenderEndTag(); for (int i = ICurrentPage - 5; i <= ICurrentPage + 5; i++) { if (i == ICurrentPage) { //添加当前选择的样式 writer.AddAttribute(HtmlTextWriterAttribute.Class, SelectCss); } writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, i + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(i.ToString()); writer.RenderEndTag(); } //添加最后一页 writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write("…"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, TotalPage + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(TotalPage.ToString()); writer.RenderEndTag(); } else if (ICurrentPage - 5 <= 2)//前面不够,后面有多余 { for (int i = 1; i <= 10; i++) { if (i == ICurrentPage) { //添加当前选择的样式 writer.AddAttribute(HtmlTextWriterAttribute.Class, SelectCss); } writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, i + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(i.ToString()); writer.RenderEndTag(); } //添加最后一页 writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write("…"); writer.RenderEndTag(); writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, TotalPage + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(TotalPage.ToString()); writer.RenderEndTag(); } else if (ICurrentPage + 7 >= TotalPage)//前面多余,后面不足 { //添加第一页 writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, 1 + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write("1"); writer.RenderEndTag(); writer.RenderBeginTag(HtmlTextWriterTag.Span); writer.Write("…"); writer.RenderEndTag(); for (int i = TotalPage - 10; i <= TotalPage; i++) { if (i == ICurrentPage) { //添加当前选择的样式 writer.AddAttribute(HtmlTextWriterAttribute.Class, SelectCss); } writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, i + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(i.ToString()); writer.RenderEndTag(); } } } if (PreNextVisable && ICurrentPage != TotalPage && TotalPage > 1) { writer.AddAttribute(HtmlTextWriterAttribute.Href, "javascript:" + Page.ClientScript.GetPostBackEventReference(this, ICurrentPage + 1 + "")); writer.RenderBeginTag(HtmlTextWriterTag.A); writer.Write(NextText); writer.RenderEndTag(); } writer.RenderEndTag(); } } #endregion /// <summary> /// 设置翻页 /// </summary> /// <param name="gotoPage"></param> protected virtual void OnPageChanged(int gotoPage) { PageChangedEventArgs e = new PageChangedEventArgs(gotoPage, TotalCount, PageSize); if (this.PageChanged != null) { PageChanged(this, e); CurrentPage = e.ECurrentPage; TotalCount = e.ETotalCount; PageSize = e.EPageSize; } } public void RaisePostBackEvent(string eventArgument) { int gotopage = Convert.ToInt32(eventArgument); OnPageChanged(gotopage); } /// <summary> /// 第一次进入页面需要显示调用 /// </summary> public void StartShowPage() { OnPageChanged(1); } /// <summary> /// 删除或更新后可以直接刷新 /// </summary> public void RefreshPage() { OnPageChanged(ICurrentPage); } } }
重要代码解释,其他可以看注释
1:控件继承自Control, IPostBackEventHandler
链接调用的为Page.ClientScript.GetPostBackEventReference()方法,点击时进入RaisePostBackEvent 方法
RaisePostBackEvent 方法实现接口IPostBackEventHandler,在进入页面时进入调用OnPageChanged()方法实现分页
2:PageChangedEventArgs 类
定义为PageChanged的参数,可以把当前的页数,总数,每页显示数带到页面进行查询,也可以在页面设置这些属性,实现控件的显示
页面使用
拖入控件,设置好属性,把要实现的数据查询和绑定写在pagechanged里面,参数里面包含了分页的参数(当前页数,每页显示数)
protected void xsPageControl1_PageChanged(object sender, PageChangedEventArgs e) { }
进入页面地方使用
xsPageControl1.StartShowPage();
页面数据修改或删除后刷新当页
xsPageControl1.RefreshPage();
源码下载
以后还会对其进行修改和完善,也可以写一下类别配合其使用,这个控件没有与其他控件关联,也没用和数据库关联,可以自行对任意需要分页显示的控件进行分页。
20140508修改
几天的测试发现了里面的bug
当前页面的刷新会找不到当前的页数,是因为页面刷新后控件类重新生成,当前页面的值也就回到了原点。
所以我考虑把CurrentPage 这个属性变为用页面缓存进行保存,经测试成功
public int CurrentPage { get { return Convert.ToInt32(ViewState[UniqueID + "xsCurrentPage"] == null ? 1 : ViewState[UniqueID + "xsCurrentPage"]); } set { ViewState[UniqueID + "xsCurrentPage"] = value; } }
20140509修改
昨天发现了一个bug,如果数据有6条,每页显示5条。我这时选到第二页,删除第6条,调用RefreshPage()是当前页面记录的2,可是由于删除其实没有第二页了。
解决办法是在OnPageChanged 发生后判断总页数和当前页,如果当前页大于总页数,执行OnPageChanged(总页数)。这样可以解决,可是得查询2遍了
请发表评论