asp.net mvc 自定义Pager实现分页

Intro

一个WEB应用程序中经常会用到数据分页,本文将实现一个简单通用的分页组件,包含一个 PagerModel (用来保存页码信息),一个 HtmlHelper 的 Pager 扩展方法和一个 PagedListModel<T> 分页数据模型。

pager效果图如下:

PagerModel 分页模型

PagerModel 用来保存分页信息,代码实现如下:

     /// <summary>
/// PagerModel 分页模型
/// </summary>
public class PagerModel
{
public int PageIndex { get; set; } public int PageSize { get; set; } public int PageCount { get; private set; } public int TotalCount { get; set; } public PagerModel(int totalCount)
{
PageIndex = ;
PageSize = ;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
} public PagerModel(int pageSize, int totalCount)
{
PageIndex = ;
PageSize = pageSize;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
} public PagerModel(int pageIndex, int pageSize, int totalCount)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
}
}

PagerModel

  /// <summary>
/// PagerModel 分页模型
/// </summary>
public class PagerModel
{
public int PageIndex { get; set; } public int PageSize { get; set; } public int PageCount { get; private set; } public int TotalCount { get; set; } public PagerModel(int totalCount)
{
PageIndex = 1;
PageSize = 10;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
} public PagerModel(int pageSize, int totalCount)
{
PageIndex = 1;
PageSize = pageSize;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
} public PagerModel(int pageIndex, int pageSize, int totalCount)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = totalCount;
PageCount = Convert.ToInt32(Math.Ceiling(TotalCount * 1.0 / PageSize));
}
}

Pager扩展方法

Pager扩展方法 可根据自己的需求进行定制话实现,Pager扩展方法需要一个PagerModel类型的参数来生成页码,我这里是用的bootstrap的样式来做的分页,整个系统用的是同一个样式的分页所以把样式直接写死在代码里了。
Pager这里的代码重构做的不是太好:

  • 样式直接写死,前端不好维护
     /// <summary>
/// PagerHelper 分页帮助类
/// </summary>
public static class PagerHelper
{
public static MvcHtmlString Pager(this HtmlHelper helper, PagerModel pager)
{
StringBuilder sbHtmlText = new StringBuilder();
sbHtmlText.Append("<div style=\"text-align:center\"><nav><ul class=\"pagination\">");
if (pager.PageIndex <= )
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData(1)\" aria-label=\"1\"><span aria-hidden=\"true\">&laquo;</span></a></li>", pager.PageIndex - );
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\">{0}</a></li>", pager.PageIndex - );
}
sbHtmlText.AppendFormat("<li class=\"active\"><a href=\"javascript:void()\">{0}<span class=\"sr-only\">(current)</span></a></li>", pager.PageIndex);
if (pager.PageIndex >= pager.PageCount)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\">{0}</a></li>", pager.PageIndex + );
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>", pager.PageIndex + );
}
sbHtmlText.Append("</ul></nav>");
sbHtmlText.AppendFormat("<div><span>每页有<strong>{0}</strong>条数据,一共有<strong>{1}</strong>页,总计<strong>{2}</strong>条数据</span></div></div>", pager.PageSize, pager.PageCount, pager.TotalCount);
return MvcHtmlString.Create(sbHtmlText.ToString());
} public static MvcHtmlString Pager(this HtmlHelper helper, PagerModel pager, Func<int, string> onPageChange)
{
StringBuilder sbHtmlText = new StringBuilder();
sbHtmlText.Append("<div style=\"text-align:center\"><nav><ul class=\"pagination\">");
if (pager.PageIndex <= )
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"{0}\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>", onPageChange(pager.PageIndex - ));
sbHtmlText.AppendFormat("<li><a href=\"{0}\">{1}</a></li>", onPageChange(pager.PageIndex - ), pager.PageIndex - );
}
sbHtmlText.AppendFormat("<li class=\"active\"><a href=\"javascript:void()\">{0}<span class=\"sr-only\">(current)</span></a></li>", pager.PageIndex);
if (pager.PageIndex >= pager.PageCount)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"{0}\">{1}</a></li>", onPageChange(pager.PageIndex+),pager.PageIndex + );
sbHtmlText.AppendFormat("<li><a href=\"{0}\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>", onPageChange(pager.PageIndex + ));
}
sbHtmlText.Append("</ul></nav>");
sbHtmlText.AppendFormat("<div><span>每页有<strong>{0}</strong>条数据,一共有<strong>{1}</strong>页,总计<strong>{2}</strong>条数据</span></div></div>", pager.PageSize, pager.PageCount, pager.TotalCount);
return MvcHtmlString.Create(sbHtmlText.ToString());
}
}

PagerHelper

  /// <summary>
/// PagerHelper 分页帮助类
/// </summary>
public static class PagerHelper
{
public static MvcHtmlString Pager(this HtmlHelper helper, PagerModel pager)
{
StringBuilder sbHtmlText = new StringBuilder();
sbHtmlText.Append("<div style=\"text-align:center\"><nav><ul class=\"pagination\">");
if (pager.PageIndex <= 1)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>", pager.PageIndex - 1);
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\">{0}</a></li>", pager.PageIndex - 1);
}
sbHtmlText.AppendFormat("<li class=\"active\"><a href=\"javascript:void()\">{0}<span class=\"sr-only\">(current)</span></a></li>", pager.PageIndex);
if (pager.PageIndex >= pager.PageCount)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\">{0}</a></li>", pager.PageIndex + 1);
sbHtmlText.AppendFormat("<li><a href=\"javascript:loadData({0})\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>", pager.PageIndex + 1);
}
sbHtmlText.Append("</ul></nav>");
sbHtmlText.AppendFormat("<div><span>每页有<strong>{0}</strong>条数据,一共有<strong>{1}</strong>页,总计<strong>{2}</strong>条数据</span></div></div>", pager.PageSize, pager.PageCount, pager.TotalCount);
return MvcHtmlString.Create(sbHtmlText.ToString());
}
}

利用 Func<> 简单重构了一下代码,可以自定义翻页事件

   public static MvcHtmlString Pager(this HtmlHelper helper, PagerModel pager, Func<int, string> onPageChange)
{
StringBuilder sbHtmlText = new StringBuilder();
sbHtmlText.Append("<div style=\"text-align:center\"><nav><ul class=\"pagination\">");
if (pager.PageIndex <= 1)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"{0}\" aria-label=\"Previous\"><span aria-hidden=\"true\">&laquo;</span></a></li>", onPageChange(pager.PageIndex - 1));
sbHtmlText.AppendFormat("<li><a href=\"{0}\">{1}</a></li>", onPageChange(pager.PageIndex - 1), pager.PageIndex - 1);
}
sbHtmlText.AppendFormat("<li class=\"active\"><a href=\"javascript:void()\">{0}<span class=\"sr-only\">(current)</span></a></li>", pager.PageIndex);
if (pager.PageIndex >= pager.PageCount)
{
sbHtmlText.Append("<li class=\"disabled\"><a href=\"javascript:void()\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>");
}
else
{
sbHtmlText.AppendFormat("<li><a href=\"{0}\">{1}</a></li>", onPageChange(pager.PageIndex+1),pager.PageIndex + 1);
sbHtmlText.AppendFormat("<li><a href=\"{0}\" aria-label=\"Next\"><span aria-hidden=\"true\">&raquo;</span></a></li>", onPageChange(pager.PageIndex + 1));
}
sbHtmlText.Append("</ul></nav>");
sbHtmlText.AppendFormat("<div><span>每页有<strong>{0}</strong>条数据,一共有<strong>{1}</strong>页,总计<strong>{2}</strong>条数据</span></div></div>", pager.PageSize, pager.PageCount, pager.TotalCount);
return MvcHtmlString.Create(sbHtmlText.ToString());
}

关于样式修改维护的问题,找到一种解决方案,可以将分页代码的样式封装在一个分部视图partial,在需要分页的页面视图,引用这个分部视图并且将分页模型信息 PagerModel 传递给这个分部视图

PagedListModel 分页数据模型

PagedListModel 用来封装返回到视图 View 的数据和 分页模型 PagerModel,实现代码如下

     /// <summary>
/// 数据分页模型
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
public class PagedListModel<T> where T : class, new()
{
public List<T> Data { get; set; } public PagerModel Pager { get; set; }
}

PagedListModel

  public class PagedListModel<T> where T : class, new()
{
public List<T> Data { get; set; } public PagerModel Pager { get; set; }
}

控制器数据处理

控制器处理代码如下:
search 是一个包含了 PageIndex 和 PageSize 的请求参数

             int rowsCount = ;
try
{
List<Models.BlockEntity> blockList = BusinessHelper.BlockEntityHelper.GetPagedList(search.PageIndex, search.PageSize, out rowsCount, whereLambda, b => b.BlockTime, false);
PagerModel pager = new PagerModel(search.PageIndex, search.PageSize, rowsCount);
PagedListModel<Models.BlockEntity> dataList = new PagedListModel<Models.BlockEntity>() { Pager = pager, Data = blockList };
return View(dataList);
}
catch (Exception ex)
{
logger.Error(ex);
throw;
}

Controller

       int rowsCount = 0;
try
{
List<Models.BlockEntity> blockList = new Business.BLLBlockEntity().GetPagedList(search.PageIndex, search.PageSize, out rowsCount, whereLambda, b => b.BlockTime, false);//记录日志
PagerModel pager = new PagerModel(search.PageIndex, search.PageSize, rowsCount);//定义Pager Model
PagedListModel<Models.BlockEntity> dataList = new PagedListModel<Models.BlockEntity>() { Pager = pager, Data = blockList };//定义返回到 View 的 PagedListModel
return View(dataList);
}
catch (Exception ex)
{
logger.Error(ex);//记录日志
throw;
}

页面处理

首先在页面顶部声明 model 模型

  @model PagedListModel<Models.BlockEntity>

在页面上遍历数据

  @foreach (Models.BlockEntity item in Model.Data)

在需要添加分页信息的地方使用 HtmlHelper 的 Pager 扩展方法

  @Html.Pager(Model.Pager)

View代码示例

 @model PagedListModel<Models.BlockEntity>
<table class="table table-hover">
<thead>
<tr>
<th>黑名单类型</th>
<th>黑名单内容</th>
<th>拉入黑名单时间</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach (Models.BlockEntity item in Model.Data)
{
string className = "bg-success";
if (!item.IsActive)
{
className = "bg-danger";
}
<tr class="@className">
<td>
@item.BlockType.TypeName
</td>
<td>
@item.BlockValue
</td>
<td>
@item.BlockTime
</td>
<td>
@if (item.IsActive)
{
<span>启用</span>
}
else
{
<span>禁用</span>
}
</td>
<td>
@if (item.IsActive)
{
<button type="button" class='btn btn-warning' onclick="UpdateStatus('@item.BlockId', '@item.BlockValue',-1,this)">禁用</button>
}
else
{
<button type="button" class='btn btn-warning' onclick="UpdateStatus('@item.BlockId','@item.BlockValue',1,this)">启用</button>
}
<button type="button" class="btn btn-danger" onclick="DeleteEntity('@item.BlockId','@item.BlockValue',this)">删除</button>
</td>
</tr>
}
</tbody>
</table>
@Html.Pager(Model.Pager)

asp.net mvc 简易通用自定义Pager实现分页的更多相关文章

  1. ASP.NET MVC如何实现自定义验证(服务端验证+客户端验证)

    ASP.NET MVC通过Model验证帮助我们很容易的实现对数据的验证,在默认的情况下,基于ValidationAttribute的声明是验证被使用,我们只需 要将相应的ValidationAttr ...

  2. asp.net mvc Route 使用自定义条件(constraints)禁止某ip登陆

    asp.net mvc Route 使用自定义条件(constraints)禁止某ip登陆 前言 本文的目的是利用Mvc route创建一个自定义约束来控制路由跳转实现禁止ip登陆,当然例子可能不合理 ...

  3. 让Asp.net mvc WebAPI 支持OData协议进行分页查询操作

    这是我在用Asp.net mvc WebAPI 支持 OData协议 做分页查询服务时的 个人拙笔. 代码已经开发到oschina上.有兴趣的朋友可以看看,欢迎大家指出不足之处. 看过了园子里的几篇关 ...

  4. 在 ASP.NET MVC 中创建自定义 HtmlHelper

    在ASP.NET MVC应用程序的开发中,我们常碰到类似Html.Label或Html.TextBox这样的代码,它将在网页上产生一个label或input标记.这些HtmlHelper的扩展方法有些 ...

  5. 在ASP.NET MVC 3 中自定义AuthorizeAttribute时需要注意的页面缓存问题

    一.ASP.NET MVC中使用OutputCache实现服务器端页面级缓存 在ASP.NET MVC中,假如我们想要将某个页面(即某个Action)缓存在服务器端,可以在Action上标上以下特性: ...

  6. asp.net mvc 中的自定义验证(Custom Validation Attribute)

    前言

  7. asp.net mvc简单实现基于Razor的分页控件

    最近在写一些web应用了解了一下asp.net mvc发现的确好用,所以直接就干上了.不过在使用asp.net mvc的Razor模板的情况并不向传统webform那样可以使用控件.但从Razor的功 ...

  8. asp.net MVC helper 和自定义函数@functions小结

    asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...

  9. [转]asp.net MVC helper 和自定义函数@functions小结

    本文转自:http://www.cnblogs.com/jiagoushi/p/3904995.html asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的 ...

随机推荐

  1. CSS系列:CSS中盒子之间的关系

    1. 标准文档流 标准文档流是值在不使用其他的雨排列和定位相关的特殊CSS规则时,各种元素的排列规则. 1.1 块级元素(block level) 块级元素不会排在同一行中,总是以一个块的形式表现出来 ...

  2. OpenCascade MeshVS Usage

    OpenCascade MeshVS Usage eryar@163.com Abstract. MeshVS means Mesh Visualization Service. It can be ...

  3. 自制编程语言crowbar(v0.1)构建解析器时分配内存

    crowbar中第一次申请内存是在生成解析器的时候: /* interface.c */CRB_Interpreter *CRB_create_interpreter(void) { MEM_Stor ...

  4. iOS开发之画图板(贝塞尔曲线)

    贝塞尔曲线,听着挺牛气一词,不过下面我们在做画图板的时候就用到贝塞尔绘直线,没用到绘制曲线的功能.如果会点PS的小伙伴会对贝塞尔曲线有更直观的理解.这篇博文的重点不在于如何用使用贝塞尔曲线,而是利用贝 ...

  5. Linux内存管理之bootmem分配器

    为什么要使用bootmem分配器,内存管理不是有buddy系统和slab分配器吗?由于在系统初始化的时候需要执行一些内存管理,内存分配的任务,这个时候buddy系统,slab分配器等并没有被初始化好, ...

  6. Spring学习笔记--环境搭建和初步理解IOC

    Spring框架是一个轻量级的框架,不依赖容器就能够运行,像重量级的框架EJB框架就必须运行在JBoss等支持EJB的容器中,核心思想是IOC,AOP,Spring能够协同Struts,hiberna ...

  7. 【LeetCode】Palindrome Pairs(336)

    1. Description Given a list of unique words. Find all pairs of distinct indices (i, j) in the given ...

  8. 关于一道PHP面试题的解法

    参照一个int型数组,如int[] a1=new int[]{10,9,10,20,15,3,9,8,7,1,1},编写一个方法,要求输出不重复,且降序的拼接字符串(连接字符用逗号),如上数组,输出的 ...

  9. Data source rejected establishment of connection, message from server: "Too many connections"解决办法

    异常名称 //数据源拒绝从服务器建立连接.消息:"连接太多" com.MySQL.jdbc.exceptions.jdbc4.MySQLNonTransientConnection ...

  10. 分享一个UI与业务逻辑分层的框架(三)

    序言 前两篇讲解了UIMediator框架的使用及具体原理代码.本篇讲述MediatorManager的实现代码及展望. MediatorManager MediatorManager的作用有两点: ...