asp.netMVC中实现分页方法
方法一:使用传统的sql语句实现分页, public class UserprintDao如下
/// <summary> /// 取得用户申请记录列表(按分页) /// </summary> /// <param name="userid"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public List<Userprint> GetUserReportListByUserId(Userprint userprint) { string sql = "select * from (select row_number() over(order by id desc) as num,* from userprint where userid=@userid "; if (!string.IsNullOrEmpty(userprint.Printname)) { sql += " and printname like @printname"; } sql += ") as t where t.num>=@start and t.num<=@end"; return DoUserprintList(sql, userprint); } //统一函数返回打印列表 public List<Userprint> DoUserprintList(string sql, Userprint userprint) { try { using (SqlConnection conn = SqlHelper.GetConn()) { return conn.Query<Userprint>(sql, userprint).ToList<Userprint>(); } } catch (Exception) { return null; } } //统一函数返回记录总数 public int DoRecordCount(string sql,Userprint userprint) { try { using (SqlConnection conn = SqlHelper.GetConn()) { return conn.ExecuteScalar(sql, userprint).ToString().ToInt32(); } } catch (Exception) { return 0; } }
/// <summary>
/// 取用户申请记录列表总数
/// </summary>
/// <param name="userprint"></param>
/// <returns></returns>
public int GetUserReportRecordCount(Userprint userprint)
{
string sql = "select count(1) from userprint where userid=@userid";
SqlParameter[] para;
if (!string.IsNullOrEmpty(userprint.Printname))
{
sql += " and printname like @printname";
}
return DoRecordCount(sql, userprint);
}
控制器中如下
public ActionResult ReprotManage() { Userprint tempuserprint = new Userprint(); var keys = Request["keys"]; if (!string.IsNullOrEmpty(keys)) { tempuserprint.Printname = "%"+keys+"%"; } tempuserprint.Userid = getUserBySession().Id; int pageIndex = Request["pageIndex"] == null ? 1 : Request["pageIndex"].ToInt32(); int pageCount = GetPageCount(tempuserprint, pageSize, printdao.GetUserReportRecordCount); int start = (pageIndex - 1) * pageSize + 1; int end = pageIndex * pageSize; tempuserprint.start = start; tempuserprint.end = end; ViewData.Model = printdao.GetUserReportListByUserId(tempuserprint); ViewBag.pageIndex = pageIndex; ViewBag.pageCount = pageCount; return View(); } //计算分页总数,使用委托合成一个函数 public int GetPageCount(Userprint userprint, int pageSize, Func<Userprint, int> GetRecordCount) { return Math.Ceiling((double)GetRecordCount(userprint) / pageSize).ToString().ToInt32(); }
在view视图添加分页代码,代码如下:
<div class="text-center">@Html.Raw(Print.PageBar.GetPageBarToUlLi(ViewBag.pageIndex, ViewBag.pageCount))</div>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; namespace Print { public class PageBar { public static string GetPageBarToUlLi(int pageIndex, int pageCount) { if (pageCount <= 1) { return string.Empty; } int start = pageIndex - 5; start = start < 1 ? 1 : start; int end = start + 9; end = end > pageCount ? pageCount : end; StringBuilder sb = new StringBuilder(); sb.Append("<nav><ul class='pagination'><li"); if (pageIndex == 1) sb.Append(" class='disabled'"); sb.Append("><a href='?pageIndex=1' aria-label='Previous'><span aria-hidden='true'>").Append("第一页").Append("</span></a></li>"); for (int i = start; i <= end; i++) { if (i == pageIndex) sb.Append("<li class='active'><a href=javascript:void(0)>" + i + "</a></li>"); else { sb.Append(string.Format("<li><a href=?pageIndex={0}>{0}</a></li>", i)); } } sb.Append("<li"); if (pageIndex == pageCount) sb.Append(" class='disabled'"); sb.Append("><a href='?pageIndex=").Append(pageCount).Append("' aria-label='Next'> <span aria-hidden='true'>最后一页</span></a></li></ul></nav>"); return sb.ToString(); } public static string GetPageBar(int pageIndex, int pageCount) { if (pageCount <= 1) { return string.Empty; } int start = pageIndex - 5; start = start < 1 ? 1 : start; int end = start + 9; end = end > pageCount ? pageCount : end; StringBuilder sb = new StringBuilder(); sb.Append("<a href=?pageIndex=1>第一页</a>"); for (int i = start; i <= end; i++) { if (i == pageIndex) sb.Append(" " + i + " "); else { sb.Append(string.Format("<a href=?pageIndex={0}>{0}</a>", i)); } } sb.Append(string.Format("<a href=?pageIndex={0}>最后一页</a>", pageCount)); return sb.ToString(); } } }
写的有点乱,这是从项目中复制出来的,其中使用到了ORM框架Dapper, js库jquery,UI美化:bootstrip,自行添加。
效果图如下:
方法二:使用第三方库PageList,添加引用 ,使用NuGet添加:PagedList,同时也会添加PagedList.Mvc
在控制器中实现如下代码:
public ActionResult Index(SearchInfo info, int page = 1){ var result=(from p in db.userprints select p).OrderByDescending(m => m.addtime).ToPagedList(page, 17); if (Request.IsAjaxRequest())
return PartialView("_statislist", statis); return View(result); }
在主视图中代码:
<div class="col-md-10"> @Html.Partial("_statislist", Model) </div>
部分视图_statislist.cshtml代码如下:
@using PagedList.Mvc @model IPagedList<Print.Entity.userprint> <div id="statislist"> <div class="pagedList" > @Html.PagedListPager(Model,page=>Url.Action("Index",new{page}),PagedListRenderOptions.Classic) </div> <table class="table table-hover table-striped"> <tr> <th> 文印名称 </th> <th> 打印色彩 </th> <th> 单双面 </th> <th> 纸张大小 </th> </tr> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.printname) </td> <td> @Html.DisplayFor(modelItem => item.printcolor) </td> <td> @Html.DisplayFor(modelItem => item.printmode) </td> <td> @Html.DisplayFor(modelItem => item.printpagersize) </td> </tr> } </table> </div>
为分页添加样式,此代码放在主视图就行
<script> $(function () { $(".pagedList a").click(function () { $.ajax({ url: $(this).attr("href"), data: $("form").serialize(), type: "get" }).done(function (data) { $("#statislist").replaceWith(data); }); }); }); </script>
效果如下:
PageList分页功能很强大,但是在实际使用中经常与查询在一起使用,如果对查询结果操作分页时,发现后面分页全乱了,最终想了一个办法解决,本人认为这样比较麻烦,但可以解决问题。思路就是:把查询的条件在页面与后台间传递。以显示用户信息为例,利用PagedLilst实现查询+分页:
1.创建类UserAndPagedList,收集后台所有传递的信息
namespace Course.Entity { public class UserAndPagedList { public User User { get; set; } public IPagedList<User> Users { get; set; } } }
2.ActionResult
public ActionResult List(User user, int page = 1) { IPagedList<User> list; if (string.IsNullOrEmpty(user.name)) list = db.Users.Where(u => u.userlevel != 2).OrderByDescending(u => u.registertime).ToPagedList<User>(page, 2); else list = db.Users.Where(u => u.userlevel != 2).Where(u => u.name.Contains(user.name)).OrderByDescending(u => u.registertime).ToPagedList<User>(page, 2); UserAndPagedList objModel = new UserAndPagedList() { User = user, Users = list }; return View(objModel); }
3.View
@using PagedList.Mvc @using Course.Entity @model Course.Entity.UserAndPagedList @{ ViewBag.Title = "List"; Layout = "~/Views/Shared/AdminLayout.cshtml"; } <style> td { font-size: 14px; } </style> @using (Html.BeginForm("List", "Admin", new AjaxOptions() { UpdateTargetId = "userlist", HttpMethod = "post", InsertionMode = InsertionMode.Replace })) { <input name="name" id="name" placeholder="用户名" class="form-control line" /> <button class="btn btn-success" type="submit">查询</button> } @Html.Partial("_userlist", Model); //视图 <script> $(function () { $("#name").width("200px").val('@Model.User.name'); //填充查询条件 $(":submit").width("60px"); }) </script>
4.部分视图_userlist
@using PagedList.Mvc @using Course.Entity @model Course.Entity.UserAndPagedList <div id="userlist"> <div class="pagedList"> @Html.PagedListPager(Model.Users, page => Url.Action("List", new { page, Model.User.name}), PagedListRenderOptions.Classic) </div> <table class="table table-hover table-striped"> <tr> <th width="150"> 用户名 </th> <th width="100"> 用户类型 </th> <th width="150"> 操作 </th> </tr> @foreach (var item in Model.Users) { <tr> <td> @Html.DisplayFor(modelItem => item.name) </td> <td> @(item.userlevel == 2 ? "管理员" : item.userlevel == 1 ? "教员" : "学生") </td> <td> @Html.ActionLink("编辑", "Edit", new { id = item.name }) @Ajax.ActionLink("删除", "Delete", new { id = item.name }, new AjaxOptions() { Confirm = "确定要删除吗?", OnSuccess = "afterOk" }) </td> </tr> } </table> </div> <script> function getValue() { return $("#name").val(); } function beginOk(data) { if (!confirm("是否要删除?")) { return false; } } function afterOk(data) { var arr = data.split(":"); if (arr[0] == "ok") { $("table tr td:contains(" + arr[1] + ")").parent().remove(); } else alert("无法删除"); } </script>
关键部位用绿色作标记了,
下面再来一个用查询+分页的例子,不过这次是在页码上作点手脚,分页时使用ajax提交,这样分页与列表部分就实现异步提交了,这个的实现刚开始走了不少弯路,实现如下:
页面上有两块,一块是查询条件,另一块是显示查询列表,列表的设计是放在分部视图中,页码也是分部视图中,代码如下:
Controllers
public ActionResult ManageCourse(Courseware cw, int firstdirectoryid = 0, int page = 1) { //第一次加载数据 ViewBag.firstDir = new SelectList( db.Firstdirectories.OrderBy(m => m.sort) .Select(m => new { id = m.id, title = m.title }).ToList() , "id", "title"); ViewBag.coursetype = new SelectList( db.Contenttypes .Select(m => new { id = m.id, name = m.name }).ToList() , "id", "name"); var list = (from c in db.Coursewares orderby c.seconddirectoryid, c.sort select c).ToPagedList<Courseware>(page, 16); return View(list); }
//分部视图 public ActionResult SysManageCourse(Courseware cw, int firstdirectoryid = 0, int page = 1) { var list = db.Coursewares.Where(x => x.id != 0); if (firstdirectoryid != 0) { if (cw.seconddirectoryid != 0) { list = list.Where(x => x.seconddirectoryid == cw.seconddirectoryid); } else { list = list.Where(x => x.Seconddirectory.firstdirectoryid == firstdirectoryid); } } if (cw.contenttypeid != 0) { list = list.Where(x => x.contenttypeid == cw.contenttypeid); } if (!string.IsNullOrEmpty(cw.title)) { list = list.Where(x => x.title.Contains(cw.title)); } var obj = list.OrderBy(x => x.seconddirectoryid).ThenBy(x => x.sort).ToPagedList<Courseware>(page, 16); return PartialView("_courselist", obj); }
主View--ManageCourse.cshtml
@using PagedList.Mvc @model PagedList.IPagedList<Course.Entity.Courseware> @{ ViewBag.Title = "ManageCourse"; Layout = "~/Views/Shared/TeacherLayout.cshtml"; } <style> td { font-size: 14px; } </style> @using (Ajax.BeginForm("SysManageCourse", "Teacher", new AjaxOptions() { UpdateTargetId = "divlist", HttpMethod = "post", InsertionMode = InsertionMode.Replace }, new { @class = "form-inline" })) { @Html.AntiForgeryToken() @Html.ValidationSummary(true) <table> <tr> <td> <div class="form-group"> <label for="firstdirectoryid">选择目录:</label> @Html.DropDownList("firstdirectoryid", ViewBag.firstDir as SelectList, "", new { @class = "form-control" }) </div> <div class="form-group"> <label for="seconddirectoryid">小节名称:</label> <select class="form-control" id="seconddirectoryid" name="seconddirectoryid"></select> </div> </td> </tr> <tr><td height="10px"></td></tr> <tr> <td> <div class="form-group"> <label for="title"> 小标题:</label> <input name="title" id="title" style="width: 300px" /> </div> <div class="form-group"> <label for="contenttypeid">课件类型:</label> @Html.DropDownList("contenttypeid", ViewBag.coursetype as SelectList, "", new { @class = "form-control" }) </div> <input type="submit" class="btn btn-success" value="查询" /> </td> </tr> </table> } <hr /> <div id="pagedPartialView"> @Html.Partial("_courselist", Model) </div> <script> $(function () { $("input").addClass("form-control").focus(function () { $(this).select(); }); $("#contenttypeid").width(50); $("#firstdirectoryid").change(function () { var value = $(this).val(); if (value == "") $("#seconddirectoryid").val(""); else { $.getJSON("GetSecondDirectoryByfirstDirectoryid", { id: $(this).val() }, function (data) { $("#seconddirectoryid option").remove(); $("<option></option>").appendTo("#seconddirectoryid"); $.each(data, function (i, v) { $("<option value='" + v.id + "'>" + v.title + "</option>").appendTo("#seconddirectoryid"); }); }); } }); }); function modify(mid, firid, title, sort) { $("#id").val(mid); $("#firstdirectoryid").val(firid); $("#title").val(title); $("#sort").val(sort); $(":submit").val("修改"); } function beginOk() { if (!confirm("是否要删除?")) { return false; } } function afterOk(data) { var arr = data.split(":"); if (arr[0] == "ok") { $("table tr td:contains(" + arr[1] + ")").parent().remove(); } else alert("无法删除"); } //function afterOk(data) { // var arr = data.split(":"); // if (arr[0] == "ok") { // $("table tr").each(function () { // if ($(this).data("delid") == arr[1]) { // $(this).remove(); // } // }); // } // else // alert("无法删除"); //} </script>
分部视图--_courselist.cshtml
@using PagedList.Mvc @model PagedList.IPagedList<Course.Entity.Courseware> <div id="divlist"> <div class="pagedList"> @Html.PagedListPager(Model, page => Url.Action("SysManageCourse", new { page }), PagedListRenderOptions.Classic) </div> @*@Html.PagedListPager(Model, page => Url.Action("SysManageCourse", new { page }), new PagedListRenderOptions() { LinkToFirstPageFormat = "首页", LinkToNextPageFormat = "下一页", LinkToPreviousPageFormat = "上一页", LinkToLastPageFormat = "末页", DisplayItemSliceAndTotal = true, ItemSliceAndTotalFormat = "共有{2}页", MaximumPageNumbersToDisplay = 6 })*@ <table class="table table-hover table-striped"> <tr> <th width="150" class="text-center"> 操作 </th> <th width="100"> 序号 </th> <th width="100"> 类型 </th> <th> 标题 </th> </tr> @foreach (var item in Model) { <tr> <td class="text-center" width="150"> @Html.ActionLink("编辑", "EditCourse", new { id = item.id }) | @Html.ActionLink("详细", "DetailsCourse", new { id = item.id }) | @Ajax.ActionLink("删除", "DeleteCourse", new { id = item.id }, new AjaxOptions() { Confirm = "确定要删除吗?", HttpMethod = "post", OnSuccess = "afterOk" }) </td> <td width="100">@Html.DisplayFor(modelItem => item.sort)</td> <td width="100"> @Html.DisplayFor(modelItem => item.Contenttype.name) </td> <td>@Html.DisplayFor(modelItem => item.title)</td> </tr> } </table> </div> <script> $(function () { $("#divlist>.pagedList>.pagination-container li a[href]").click(function () { var href = $(this).attr("Href"); $.post(href, $("#form0").serialize(), function (data) { $("#pagedPartialView").html(data); }); return false; }); }); </script>
代码中有多余的内容,由于是直接复制过来,自己挑着看,要注意的是在分部视图中对页码的click事件(就是上面绿色的部分,屏蔽点击直接跳转,用异步ajax跳转)一定要写在分部视图中,如果写在主视图中那就惨了,点击页面会直接跳转,根本就不经过JS,原因时ajax分页后返回数据重写了分部视图中的所有元素,前面的JS对后面重写的不起作用,所以一定要写在分部视图中,刚开始我就是把它写在了主视图中,折腾1个小时才明白。$.post提交时把查询块form中的数据传递给了后台。
另外提供两种分页方式:
<div class="pagedList"> @Html.PagedListPager(Model, page => Url.Action("SysManageCourse", new { page }), PagedListRenderOptions.Classic) </div>
@Html.PagedListPager(Model, page => Url.Action("SysManageCourse", new { page }), new PagedListRenderOptions() { LinkToFirstPageFormat = "首页", LinkToNextPageFormat = "下一页", LinkToPreviousPageFormat = "上一页", LinkToLastPageFormat = "末页", DisplayItemSliceAndTotal = true, ItemSliceAndTotalFormat = "共有{2}页", MaximumPageNumbersToDisplay = 6 }