去年就發表過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遍了