【发布】弹性分页类PagingBuild Class 附带测试
园子里分页代码是老生常谈了,可惜找到的不是有问题就是满足不了自己的需求,静下心来重新改写了在用的一个分页器,因为有测试会比较稳定,虽然测试覆盖可能还不是很全面。
用例代码:
new CNBlogs.Presentation.Web.PagingBuilder() { FirstPageLink = firstLink, OnlickJsFunc = "Return true;" , PageIndex = ( int )(p??1), ShowPageCount = 11, TotalCount = 1, UrlFormat = urlFormate, PageSize = PAGE_SIZE, AjaxUrl = "/" }; //MVC View Code @{ Html.RenderPaging(Model.Paging); } |
先上代码:
public class PagingBuilder { private TextWriter _writer; private int _totalCount; private int _pageIndex; private int _pageSize; private int _showPageCount; private string _urlFormat; private string _onclickJsFunc; private string _firstPageLink; private string _ajaxUrl = "/ToolkitPaging/load" ; private int _totalPageCount; private int _lastPage = 1; #region Properties public bool OnlyLinkText { get ; set ; } /// <summary> /// 总记录数 /// </summary> public int TotalCount { get { return _totalCount; } set { _totalCount = value; } } /// <summary> /// 当前页码 /// </summary> public int PageIndex { get { return _pageIndex; } set { _pageIndex = value; } } /// <summary> /// 每页显示的记录数 /// </summary> public int PageSize { get { return _pageSize; } set { _pageSize = value; } } /// <summary> /// 默认显示的页码数 /// </summary> public int ShowPageCount { get { return _showPageCount; } set { _showPageCount = value; } } /// <summary> /// 页码链接地址 /// </summary> public string UrlFormat { get { return _urlFormat; } set { _urlFormat = value; } } /// <summary> /// 页码链接onclick事件处理js方法,pageIndex,pageSize参数无需添加 /// </summary> public string OnlickJsFunc { get { return _onclickJsFunc; } set { _onclickJsFunc = value; } } /// <summary> /// 第1页链接地址 /// </summary> public string FirstPageLink { get { return _firstPageLink; } set { _firstPageLink = value; } } /// <summary> /// ajax加载分页的请求地址,默认是/paging/load /// </summary> public string AjaxUrl { get { return _ajaxUrl; } set { _ajaxUrl = value; } } /// <summary> /// ajax加载分页的js回调方法,有默认实现 /// </summary> private string _ajaxCallbak; public string AjaxCallbak { get { return _ajaxCallbak; } set { _ajaxCallbak = value; } } /// <summary> /// 顶部分页Html标签Id /// </summary> private string _topPagerId = "pager_top" ; public string TopPagerId { get { return _topPagerId; } set { _topPagerId = value; } } public bool IsRenderScript { get ; set ; } #endregion public PagingBuilder() { IsRenderScript = true ; } public void Render(TextWriter writer) { _writer = writer; Render(); } public void Render() { if (_totalCount <= _pageSize) { return ; } if ( this .IsRenderScript) { _writer.Write( "<div id=\"paging_block\">" ); } if (! this .OnlyLinkText) { _writer.Write( "<div class=\"pager\">" ); } //总页数 _totalPageCount = (_totalCount + _pageSize - 1) / _pageSize; int currint = _showPageCount / 2; if (_pageIndex - currint <= 1) { Head(); } else if (_pageIndex + currint >= _totalPageCount) { Tail(); } else { Middle(); } if (! this .OnlyLinkText) { _writer.Write( "</div>" ); } if (IsRenderScript) { _writer.Write( "</div>" ); RenderScript(); } } private void Head() { int totalPageCount = _totalPageCount; int currint = _showPageCount / 2; if (_pageIndex > 1) { //处理上一页的连接 RenderPage(_pageIndex - 1, this .OnlyLinkText ? "Prev " : "< Prev" ); } for ( int i = 1; i <= (_showPageCount > totalPageCount ? totalPageCount : _showPageCount); i++) { RenderPage(i); } if (_lastPage + 1 < totalPageCount) { _writer.Write( "..." ); } if (_lastPage < totalPageCount) { RenderPage(totalPageCount); } if (_pageIndex < totalPageCount) { //处理下一页的链接 RenderPage(_pageIndex + 1, this .OnlyLinkText ? "Next" : "Next >" ); } } private void Middle() { int totalPageCount = _totalPageCount; int currint = _showPageCount / 2; if (_pageIndex > 1) { //处理上一页的连接 RenderPage(_pageIndex - 1, this .OnlyLinkText ? "Prev " : "< Prev" ); } if (_pageIndex - currint > 1) { //处理首页连接 RenderPage(1); if (_pageIndex-currint>2) {_writer.Write( "..." );} } for ( int i = 0; i <= _showPageCount; i++) { var c = _pageIndex + i - currint; //一共最多显示10个页码,前面5个,后面5个 if (c > 1 && c < totalPageCount) { if (c != 2 && _lastPage == 1) { _writer.Write( "..." ); } RenderPage(c); } } if (_pageIndex + currint < totalPageCount) { if (_lastPage + 1 != totalPageCount) { _writer.Write( "..." ); } RenderPage(totalPageCount); } if (_pageIndex < totalPageCount) { //处理下一页的链接 RenderPage(_pageIndex + 1, this .OnlyLinkText ? "Next" : "Next >" ); } } private void Tail() { int totalPageCount = _totalPageCount; int currint = _showPageCount / 2; if (_pageIndex > 1) { //处理上一页的连接 RenderPage(_pageIndex - 1, this .OnlyLinkText ? "Prev " : "< Prev" ); } if (_pageIndex - currint > 1&&_totalPageCount>_showPageCount) { //处理首页连接 RenderPage(1); } for ( int i = ((_totalPageCount - _showPageCount) < 0 ? 0 : (_totalPageCount - _showPageCount)) + 1; i <= _totalPageCount; i++) { if (i > 2 && _lastPage == 1) { _writer.Write( "..." ); } RenderPage(i); } if (_pageIndex < totalPageCount) { //处理下一页的链接 RenderPage(_pageIndex + 1, this .OnlyLinkText ? "Next" : "Next >" ); } } private void RenderPage( int pageIndex) { RenderPage(pageIndex, string .Empty); } private void RenderPage( int pageIndex, string pageText, bool visible = true ) { _lastPage = pageIndex; if (OnlyLinkText) { if (pageIndex == _pageIndex) { _writer.Write( "-" ); } _writer.Write( " " ); if (! string .IsNullOrEmpty(pageText)) { _writer.Write(pageText); } else { _writer.Write(pageIndex); } if (pageIndex == _pageIndex) { _writer.Write( "-" ); } return ; } string link = "" ; if ( string .IsNullOrEmpty(_urlFormat)) { link = "javascript:void(0)" ; } else { if (pageIndex == 1 && ! string .IsNullOrEmpty(_firstPageLink)) { link = _firstPageLink; } else { link = string .Format(_urlFormat, pageIndex); } } _writer.Write( "<a href=\"" ); _writer.Write(link); _writer.Write( "\"" ); //style if (!visible) { _writer.Write( " style=\"display:none\"" ); } #region class if ( string .IsNullOrEmpty(pageText)) { _writer.Write( " class=\"p_" ); _writer.Write(pageIndex); if (pageIndex == _pageIndex) { _writer.Write( " current" ); } _writer.Write( "\"" ); } #endregion #region onclick if (! string .IsNullOrEmpty(_onclickJsFunc)) { _writer.Write( " onclick=\"" ); if (_onclickJsFunc.IndexOf( "()" ) < 0) { _writer.Write(_onclickJsFunc.Replace( ")" , "," + pageIndex + "," + _pageSize + ")" )); } else { _writer.Write(_onclickJsFunc.Replace( "()" , "(" + pageIndex + "," + _pageSize + ")" )); } _writer.Write( ";buildPaging(" + pageIndex + ");return false;" ); _writer.Write( "\"" ); } #endregion #region id //if (pageText.IndexOf("<") > -1) //{ // _writer.Write(" id=\"paging_p_prev\""); //} //else if (pageText.IndexOf(">") > -1) //{ // _writer.Write(" id=\"paging_p_next\""); //} #endregion _writer.Write( ">" ); if ( string .IsNullOrEmpty(pageText)) { _writer.Write(pageIndex); } else { _writer.Write(pageText); } _writer.Write( "</a>" ); } private void RenderScript() { _writer.Write( "<script type=\"text/javascript\">" ); _writer.Write( "function buildPaging(pageIndex){var pagingBuider=" ); _writer.Write(JsonConvert.SerializeObject( this )); _writer.Write( ";" ); _writer.Write( "pagingBuider.pageIndex=pageIndex;" ); _writer.Write( "$.ajax({url:pagingBuider.AjaxUrl,data:JSON.stringify(pagingBuider)," ); _writer.Write( "type:'post',dataType:'text',contentType:'application/json; charset=utf-8'," ); _writer.Write( "success:function (data) { $('#paging_block').html(data); " ); _writer.Write( "var pagerTop=$('#" ); _writer.Write(_topPagerId); _writer.Write( "');" ); _writer.Write( "if(pageIndex>1){$(pagerTop).html(data).show();}else{$(pagerTop).hide();}}});" ); _writer.WriteLine( "}</script>" ); } } |
测试分页效果,这里设定的弹性显示页数为11:
Render_Test : Passed
1//1
Result:
1//2
Result:- 1- 2 Next
2//2
Result: Prev 1- 2-
1//3
Result:- 1- 2 3 Next
2//3
Result: Prev 1- 2- 3 Next
3//3
Result: Prev 1 2- 3-
1//9
Result:- 1- 2 3 4 5 6 7 8 9 Next
3//9
Result: Prev 1 2- 3- 4 5 6 7 8 9 Next
5//9
Result: Prev 1 2 3 4- 5- 6 7 8 9 Next
7//9
Result: Prev 1 2 3 4 5 6- 7- 8 9 Next
9//9
Result: Prev 1 2 3 4 5 6 7 8- 9-
1//11
Result:- 1- 2 3 4 5 6 7 8 9 10 11 Next
3//11
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11 Next
5//11
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11 Next
7//11
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 Next
10//11
Result: Prev 1 2 3 4 5 6 7 8 9- 10- 11 Next
1//13
Result:- 1- 2 3 4 5 6 7 8 9 10 11... 13 Next
3//13
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11... 13 Next
5//13
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11... 13 Next
7//13
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 12 13 Next
8//13
Result: Prev 1... 3 4 5 6 7- 8- 9 10 11 12 13 Next
9//13
Result: Prev 1... 3 4 5 6 7 8- 9- 10 11 12 13 Next
10//13
Result: Prev 1... 3 4 5 6 7 8 9- 10- 11 12 13 Next
11//13
Result: Prev 1... 3 4 5 6 7 8 9 10- 11- 12 13 Next
12//13
Result: Prev 1... 3 4 5 6 7 8 9 10 11- 12- 13 Next
1//200
Result:- 1- 2 3 4 5 6 7 8 9 10 11... 200 Next
3//200
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11... 200 Next
5//200
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11... 200 Next
7//200
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 12 13... 200 Next
8//200
Result: Prev 1...... 3 4 5 6 7- 8- 9 10 11 12 13 14... 200 Next
9//200
Result: Prev 1...... 4 5 6 7 8- 9- 10 11 12 13 14 15... 200 Next
10//200
Result: Prev 1...... 5 6 7 8 9- 10- 11 12 13 14 15 16... 200 Next
11//200
Result: Prev 1...... 6 7 8 9 10- 11- 12 13 14 15 16 17... 200 Next
12//200
Result: Prev 1...... 7 8 9 10 11- 12- 13 14 15 16 17 18... 200 Next
88//200
Result: Prev 1...... 83 84 85 86 87- 88- 89 90 91 92 93 94... 200 Next
199//200
Result: Prev 1... 190 191 192 193 194 195 196 197 198- 199- 200 Next
Result:
1//2
Result:- 1- 2 Next
2//2
Result: Prev 1- 2-
1//3
Result:- 1- 2 3 Next
2//3
Result: Prev 1- 2- 3 Next
3//3
Result: Prev 1 2- 3-
1//9
Result:- 1- 2 3 4 5 6 7 8 9 Next
3//9
Result: Prev 1 2- 3- 4 5 6 7 8 9 Next
5//9
Result: Prev 1 2 3 4- 5- 6 7 8 9 Next
7//9
Result: Prev 1 2 3 4 5 6- 7- 8 9 Next
9//9
Result: Prev 1 2 3 4 5 6 7 8- 9-
1//11
Result:- 1- 2 3 4 5 6 7 8 9 10 11 Next
3//11
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11 Next
5//11
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11 Next
7//11
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 Next
10//11
Result: Prev 1 2 3 4 5 6 7 8 9- 10- 11 Next
1//13
Result:- 1- 2 3 4 5 6 7 8 9 10 11... 13 Next
3//13
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11... 13 Next
5//13
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11... 13 Next
7//13
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 12 13 Next
8//13
Result: Prev 1... 3 4 5 6 7- 8- 9 10 11 12 13 Next
9//13
Result: Prev 1... 3 4 5 6 7 8- 9- 10 11 12 13 Next
10//13
Result: Prev 1... 3 4 5 6 7 8 9- 10- 11 12 13 Next
11//13
Result: Prev 1... 3 4 5 6 7 8 9 10- 11- 12 13 Next
12//13
Result: Prev 1... 3 4 5 6 7 8 9 10 11- 12- 13 Next
1//200
Result:- 1- 2 3 4 5 6 7 8 9 10 11... 200 Next
3//200
Result: Prev 1 2- 3- 4 5 6 7 8 9 10 11... 200 Next
5//200
Result: Prev 1 2 3 4- 5- 6 7 8 9 10 11... 200 Next
7//200
Result: Prev 1 2 3 4 5 6- 7- 8 9 10 11 12 13... 200 Next
8//200
Result: Prev 1...... 3 4 5 6 7- 8- 9 10 11 12 13 14... 200 Next
9//200
Result: Prev 1...... 4 5 6 7 8- 9- 10 11 12 13 14 15... 200 Next
10//200
Result: Prev 1...... 5 6 7 8 9- 10- 11 12 13 14 15 16... 200 Next
11//200
Result: Prev 1...... 6 7 8 9 10- 11- 12 13 14 15 16 17... 200 Next
12//200
Result: Prev 1...... 7 8 9 10 11- 12- 13 14 15 16 17 18... 200 Next
88//200
Result: Prev 1...... 83 84 85 86 87- 88- 89 90 91 92 93 94... 200 Next
199//200
Result: Prev 1... 190 191 192 193 194 195 196 197 198- 199- 200 Next
作者:today4king
出处:https://www.cnblogs.com/jinzhao/archive/2012/07/12/2587838.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架