在这篇MVC学习(四)几种分页的实现(2)博文中,根据URL中传入的两个参数(页码数,首页、上一页、下一页、末页的标记符)来获得对应的分页数据,

只是传入的参数太多,调用起来不太方便(标记符不能够写错,需要添加新的路由),因此,如果URL只传入页码数就太好,顺着这个思路,有了第三种分页方式。

实现分页形式如下图所示。

  下面说说我的思路吧。

  为了在试图文件中呈现<input type="text" ...> ,我们需要写上代码@Html.TextBox(Asp.net MVC 3语法),为了呈现Lable,需要写@Html.Label,

这里的@Html,有一个管理它的类 HtmlHelper。为了使用方便,我决定对HtmlHelper类进行扩展。

   考虑到有些页面不需要“上一页”,“下一页”之间的“100001”,因此,决定由两种呈现形式,一个是普通的分页,一个是带数字的分页,只有两种分页模式,新建一个枚举类型PageMode,代码如下

/// <summary>/// 分页模式/// </summary>public enum PageMode{/// <summary>/// 普通分页模式/// </summary>
        Normal,/// <summary>/// 普通分页加数字分页/// </summary>
        Numeric}

enum PageMode

  面向对象,对象总是很重要的,因此,页面对象是首先需要抽象出来的。

   我希望展现的形式是 “总共XX条记录,共XX页,当前第X页 首页 1 2... 上一页 下一页 末页”,想想这段话中,“记录数量”,“共多少页”,“第几页”,还有一条隐形“每页展示数据的大小”,因此,抽象出页面对象PagerInfo(TotalPageCount可以放入这个类中),代码如下。

    public class PagerInfo{public int RecordCount { get; set; }public int CurrentPageIndex { get; set; }public int PageSize { get; set; }}

  第一步,如何扩展HtmlHelper。

   首先,给大家看看微软如何@Html.Label的代码,看下面的截图

   在研究了这段代码后,就可以写一个普通的HtmlHelper扩展了,代码如下

 public static MvcHtmlString Pager(this HtmlHelper helper, string id, int currentPageIndex, int pageSize, int recordCount, object htmlAttributes, string className, PageMode mode){TagBuilder builder = new TagBuilder("table");builder.IdAttributeDotReplacement = "_";builder.GenerateId(id);builder.AddCssClass(className);builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));return builder.ToMvcHtmlString(TagRenderMode.Normal);}

  "string id"表示这个控件的id号,“int currentPageIndex”表示需要显示第几页数据的页码,

  “int pageSize"表示每页显示数据的大小,”object htmlAttributes“表示属性, ”string className“表示样式属性。

  看了我的HtmlHepler扩展代码,在与微软的原始代码比较以后,会发现我少了一行重要的代码,就是”tagBuilder.SetInnerText(str);“,即控件在View

的呈现形式。无论是asp.net WebForm页面的服务器控件,还是类似"<input type="text" runat="server">”控件,或者是asp.net MVC的@Html.Label,

他们在页面的都是以字符串的形式展现。

  有了这个思路,写出普通的分页形式就比较简单了。

  我们只需要给TagBuilder给予正确的字符串就行了。

  1、首先获得总的记录数,总页数

    总记录数 int pageCount =Convert.ToInt32(Math.Ceiling((double)RecordCount / (double)PageSize));//获得总页数

  2、普通分页如何实现

   假设我们的url形式为 “http://localhost:11507/Home/FY3?page=2”,那么下一页的url形式便是“http://localhost:11507/Home/FY3?page=3”,因此,我们需要得到传来的绝对路径,不含任何参数。然后根据传来的当前页码数,判断是否有下一页,上一页,并且得到格式化后的url。

   这里我先理一理页码数如何传入HtmlHelper中的。

   首先,Controller从URL中获取CurrentPageIndex,然后放入PageInfo对象,并且获得分页数据(InfoSource);

   然后,我们将InfoSource与PageInfo两个对象放入一个泛型容器PagerQuery<T>,返回给View;

   最后,HtmlHelper根据View页面中的对象获得所需参数。

  

现在回到HtmlHelper的扩展实现。

  获得我们需要ULR格式化字符串,如下代码。

  var url=new StringBuilder();

  url.Append(HttpContext.Current.Request.Url.AbsolutePath+"?page={0}");

  我希望展现的形式是 “总共XX条记录,共XX页,当前第X页 首页 上一页 下一页 末页”。现在开始拼字符串。

   var sb=new StringBuilder();

   sb.Append("<tr><td>");

   sb.AppendFormat("总共{0}条记录,共{1}页,当前第{2}页&nbsp;&nbsp;",RecordCount,pageCount,currentPageIndex);

  //RecordCount,currentPageIndex 值通过PagerInfo传递过来

  if(currentPageIndex==1{

    sb.Append("<span>首页</span>&nbsp;";)   //如果第一页 不需要给首页真实的链接
  }

  else{

    var url1=string.Format(url.ToString(),1);  //格式化URL 得到第一页的url   “http://localhost:11507/Home/FY3?page=1”

    sb.AppendFormat("<span><a href={0} 首页</a></span>&nbsp;",url1);

  }

  如何类推,可得到上一页、下一页、末页的链接。

    那么,如果上一页与下一页需要显示数字,怎么办呢? 这里,默认显示10个数字(如果页数不够,就按实际页数显示)

private static string GetNumericPage(int currentPageIndex, int pageSize, int recordCount, int pageCount, string url){var k = currentPageIndex / 10;var m = currentPageIndex % 10;var sb = new StringBuilder();if (currentPageIndex / 10 == pageCount / 10)//10个号码 为一组
            {if (m == 0){k--;m = 10;}elsem = pageCount % 10;}elsem = 10;for (var i = k * 10 + 1; i <= k * 10 + m; i++)//如果是第1页 则 1...10 第11页,则11...20//for(int i=currentPageIndex;i<LastPage;i++)
            {if (i == currentPageIndex)sb.AppendFormat("<span><font color=red><b>{0}</b></font></span>&nbsp;", i);else{var url1 = string.Format(url, i);sb.AppendFormat("<span><a href={0}>{1}</a></span>&nbsp;", url1, i);}}return sb.ToString();}}

string GetNumericPage

    现在,可以得到扩展标签代码,如下

public static MvcHtmlString Pager(this HtmlHelper helper, string id, int currentPageIndex, int pageSize, int recordCount, object htmlAttributes, string className, PageMode mode){TagBuilder builder = new TagBuilder("table");builder.IdAttributeDotReplacement = "_";builder.GenerateId(id);builder.AddCssClass(className);builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));builder.InnerHtml = GetNormalPage(currentPageIndex, pageSize, recordCount, mode);return builder.ToMvcHtmlString(TagRenderMode.Normal);}static MvcHtmlString ToMvcHtmlString(this TagBuilder tagBuilder, TagRenderMode renderMode){return new MvcHtmlString(tagBuilder.ToString(renderMode));}

    得到分页字符串代码了,如下

private static string GetNormalPage(int currentPageIndex, int PageSize, int RecordCount, PageMode mode){int pageCount =Convert.ToInt32(Math.Ceiling((double)RecordCount / (double)PageSize));//获得总页数var url = new StringBuilder();url.Append(HttpContext.Current.Request.Url.AbsolutePath + "?page={0}");var sb = new StringBuilder();sb.Append("<tr><td>");sb.AppendFormat("总共{0}条记录,共{1}页,当前第{2}页&nbsp;&nbsp;", RecordCount, pageCount, currentPageIndex);if (currentPageIndex == 1)sb.Append("<span>首页</span>&nbsp;");else{var url1 = string.Format(url.ToString(), 1);sb.AppendFormat("<span><a href={0}>首页</a></span>&nbsp;", url1);}if (currentPageIndex > 1){var url1 = string.Format(url.ToString(), currentPageIndex - 1);sb.AppendFormat("<span><a href={0}>上一页</a></span>&nbsp;", url1);}elsesb.Append("<span>上一页</span>&nbsp;");if (mode == PageMode.Numeric)sb.Append(GetNumericPage(currentPageIndex, PageSize, RecordCount, pageCount, url.ToString()));if (currentPageIndex < pageCount){string url1 = string.Format(url.ToString(), currentPageIndex + 1);sb.AppendFormat("<span><a href={0}>下一页</a></span>&nbsp;", url1);}elsesb.Append("<span>下一页</span>&nbsp;");if (currentPageIndex == pageCount)sb.Append("<span>末页</span>&nbsp;");else{string url1 = string.Format(url.ToString(), pageCount);sb.AppendFormat("<span><a href={0}>末页</a></span>&nbsp;", url1);}return sb.ToString();}

GetNormalPage(int currentPageIndex, int PageSize, int RecordCount, PageMode mode)

   那么,承载数据的容器时什么呢,因为Model是会随时变化的(泛型类最佳实现),代码如下

public class PagerQuery<T> : List<T>{public PagerQuery(PagerInfo pager, IEnumerable<T> source){this.Pager = pager;int BeforePageIndex = pager.CurrentPageIndex - 1;if (BeforePageIndex < 0){BeforePageIndex = 1;}var entityList = source.Skip((BeforePageIndex) * pager.PageSize).Take(pager.PageSize);AddRange(entityList);}public PagerInfo Pager { get; set; }}

   Controller代码如下

public ActionResult FY2(int? page){LZSEntities _lzsDb=new LZSEntities();PagerInfo pager = new PagerInfo();pager.RecordCount = _lzsDb.MyTestPages.Count();pager.PageSize = 5;if (page == null){pager.CurrentPageIndex = 1;}else{pager.CurrentPageIndex = Convert.ToInt32(page);}var result = _lzsDb.MyTestPages;IEnumerable<MyTestPages> info2 = result;var query = new PagerQuery<MyTestPages>(pager, info2);return View(query);}

public ActionResult FY2(int? page)

   View代码如下

@model MVCFY2.PageHelpers.PagerQuery<MVCFY2.Models.MyTestPages>
@using MVCFY2.Models
@using MVCFY2.PageHelpers;
@{Layout = null;
}<!DOCTYPE html><html><head><title>FY3</title></head>
<body>
@* ReSharper disable once Html.Obsolete *@<table cellpadding="0" cellspacing="0" height="200px" width="300px" bordercolor="blue"><tr><th height="30px">序号</th></tr>@foreach (var item in Model){<tr><td align="center" height="30px">@item.Id</td></tr>}</table><div><p> @Html.Pager("pager1", Model.Pager.CurrentPageIndex, Model.Pager.PageSize, Model.Pager.RecordCount, PageMode.Numeric)</p></div>
</body>
</html>

View

 VS 2010 MVC3,配置好数据库后,运行即可,源代码点此下载。

  我感觉,第三种分页形式是很完美的,只是重复从第一页跳到最后一页再最后一页跳至第一页,分页缓慢,查看资源管理器,内存被占了很多,未曾释放,因此,

希望各位可以告诉我高效的改进方法~~~

  

转载于:https://www.cnblogs.com/xianrongbin/p/3487807.html

MVC学习(四)几种分页的实现(3)相关推荐

  1. sqlserver的四种分页方式

    第一种:ROW_NUMBER() OVER()方式 select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId f ...

  2. sql server和mysql 分页_基于Sql server数据库的四种分页方式总结

    下面小编就为大家分享一篇基于sqlserver的四种分页方式总结,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧. 第一种:ROW_NUMBER() OVER()方式 select * ...

  3. Windows x64内核学习笔记(四)—— 9-9-9-9-12分页

    Windows x64内核学习笔记(四)-- 9-9-9-9-12分页 前言 9-9-9-9-12分页 实验一:线性地址转物理地址 页表基址 定位基址 PTE to PXE 实验二:通过页表基址定位各 ...

  4. SqlServer常用的几种分页查询SQL语句介绍、对比以及在.Net下的使用

    前言 在实际开发过程中,当数据量比较多的时候,大量的数据一下子展示到页面上是非常不可取的.所以我们通常要进行分页(这里的分页是指真分页),而不是前端JS实现的假分页.     最近的学习过程中,使用A ...

  5. FineUIMvc随笔(6)对比WebForms和MVC中表格的数据库分页

    声明:FineUIMvc(基础版)是免费软件,本系列文章适用于基础版. 通过对比WebForms和MVC中表格数据库分页代码的不同,可以对 MVC 中的数据流转有更加深入的了解. WebForms 中 ...

  6. Spring MVC 学习总结(九)——Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务)...

    Spring MVC 学习总结(九)--Spring MVC实现RESTful与JSON(Spring MVC为前端提供服务) 目录 一.JSON 1.1.概要 1.2.使用ModelAndView ...

  7. ASP.NET MVC学习之控制器篇

    一.前言 许久之后终于可以继续我的ASP.NET MVC连载了,之前我们全面的讲述了路由相关的知识,下面我们将开始控制器和动作的讲解. ASP.NET MVC学习之路由篇幅(1) ASP.NET MV ...

  8. Spring MVC 学习总结(五)——校验与文件上传 转自 张果 博客;已经编程校验;正确无误;...

    Spring MVC 学习总结(五)--校验与文件上传 目录 一.Spring MVC验证器Validator 1.1.定义验证器 1.2.执行校验 1.3.在UI中添加错误标签 1.4.测试运行 二 ...

  9. (转)ASP.NET MVC 学习第一天

    天道酬勤0322 博客园 | 首页 | 发新随笔 | 发新文章 | 联系 | 订阅  | 管理 随笔:10 文章:0 评论:9 引用:0 ASP.NET MVC 学习第一天 今天开始第一天学习asp. ...

最新文章

  1. MSBuild学习总结
  2. 啊啊啊...每次需求评审总被boss虐成狗?解药来了
  3. pat 1034. Head of a Gang (30)
  4. 【+】Linux Socket编程
  5. UmiJS CDN 部署之 publicPath
  6. python 菜单 阻塞 其它程序_Python subprocess.call阻塞
  7. GitHub#python#:用自组织映射解决旅行商问题
  8. BZOJ1076奖励关题解
  9. 对网易云音乐软件的看法
  10. R语言混合效应(多水平/层次/嵌套)模型及贝叶斯实现
  11. ​LeetCode刷题实战317:离建筑物最近的距离
  12. excel拆分单元格内容_Excel 快捷键合集
  13. 【图像分割】基于计算机视觉实现视网膜图像中的血管分割附matlab代码
  14. JavaWeb jQuery
  15. VBA:新增某个月的FC至Excel版物料Forecast
  16. v-chart柱状图点击改变颜色
  17. 青桔单车 chameleon 跨平台实践分享
  18. 关于“搭桥”游戏生成随机地图的设计思路
  19. 基于webrtc的视频聊天室(六)之客户端设计
  20. ubuntu 下查看网卡流量速度

热门文章

  1. Hadoop单机/伪分布式集群搭建(新手向)
  2. K.O. -------- Eclipse中Maven的报错处理
  3. spring装配Bean过程
  4. A winner is a dreamer who never gives up
  5. javascript中错误使用var造成undefined
  6. C#日期格式化(转)
  7. react native 学习笔记
  8. C#面向对象9 字符串
  9. 借助 Evolution Linux 的帮助来轻松安装 Arch Linux
  10. 定时任务:Java中Timer和TimerTask的使用