ASP.NET MVC之PagedList使用
ASP.NET MVC之PagedList使用
---由于最近项目中用到了分页这里也来记录一下,一方面给自己一个记录,另一方面给后来者一些帮助!
一、首先大家先来看一下效果
二、然后说一下穿插的技术
- MVC5
- PagedList
- EF6
- @helper
- Regex
- Autofac
- 伪静态
暂时想到这些
三、细说下PagedList及其比较其他分页
PagedList是NuGet上提供的一个分页的类库,能对任何 IEnumerable<T>进行分页,而且非常简单好用。从NuGet上,可以获取两个DLL:PagedList.dll和 PagedList.Mvc.dll。PagedList.dll提供分页的核心操作,PagedList.Mvc.dll是一个辅助类库,在创建分页的 UI时候提供简单、可扩展的创建方法。不过PagedList.dll可以用于MVC2及其以上,但是PagedList .Mvc.dll只能用于MVC3(及其以上)。
2014年开始,作者改名为X.PagedList.Mvc,听说用这个插件的话会非常便利,大家可以试试(自己没用过只是听说)。
我的项目中主要是PagedList.Mvc.4.5.0.0 和PagedList.1.17.0.0
在选择分页插件的时候,nuget上的下载量直接决定了我的使用。pagedlist暂时还没有实现异步,这方面mvcpager 倒是可以,但是写起来比较麻烦,还有繁琐的js,这
是不是我想要的。
四、使用PagedList
大家可以直接使用nuget安装PagedList.Mvc,期间会连同PageList一起装上。完成以后会看到项目中多了着两个引用:
刚开始自己也是使用的ToPagedList() 但这样会取出所有的数据在分页,所以后来就用了StaticPagedList(System.Collections.Generic.IEnumerable<T> subset, int pageNumber, int pageSize, int totalItemCount),接下来就直说后者了。
可以看到,StaticPagedList需要将:某一页的数据、页码、每页数据的容量、和数据总条目传入。也就是说这时候StaticPagedList不再像PagedList一样承担数据的划分工作,而仅仅承担数据的绑定操作,上面也说到了我的项目中用了aotufac,所以对两个方法进行了封装,直接上代码
public virtual List<T> GetPageList<TKey, TTKey>(Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, Expression<Func<T, TTKey>> thenorder, int pageIndex, int pageSize, ref int totalCount, bool IsDesc1 = true,bool IsDesc2=true) { IQueryable<T> data = null; if (IsDesc1) { if (IsDesc2) { data = dbset.Where(where).OrderByDescending(order).ThenByDescending(thenorder).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking(); } else { data = dbset.Where(where).OrderByDescending(order).OrderBy(thenorder).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking(); } } else { if (IsDesc2) { data = dbset.Where(where).OrderBy(order).ThenByDescending(thenorder).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking(); } else { data = dbset.Where(where).OrderBy(order).ThenBy(thenorder).Skip((pageIndex - 1) * pageSize).Take(pageSize).AsNoTracking(); } } totalCount = dbset.Where(where).Count(); return data.ToList(); }
public virtual StaticPagedList<T> GetStaticPageList(List<T> data, int pageIndex, int pageSize, int totalCount) { return new StaticPagedList<T>(data, pageIndex, pageSize, totalCount); }
下面是上面两个方法的使用,其中articleRepository你就可以认为是一个实体类。
public ActionResult Index(int page = 1) { int pageIndex = page; int pageSize = PageCount; int totalCount = 0; var article = articleRepository.GetPageList(m => true, m => m.IsTop,m=>m.PublishDate, pageIndex, pageSize, ref totalCount); var staticPageList = articleRepository.GetStaticPageList(article, pageIndex, pageSize, totalCount); return View("article", staticPageList); }
再来看一些View,其中mode的类型以及PagedListPager的参数类型 于 ToPagedList()的时候是不一样的
如果做到以上基本上就可以实现分页了,但是还由于使用了伪静态,而PagedList分页时是这样 ?page=2 传递参数的,就是让url很不友好,所搜了半天看往上说
PagedList可以直接使用 /id 来传递参数,但是自己没能实现了,coder友如果可以实现,请告知。而最终我选择l利用 @helper 修改的方式来实现
下面是我的PageHelpers.cshtml的代码,当然也通过重写HtmlHelper的方式来实现,不过感觉这样更好一些,写起来更方便一些,尤其是怕对于拼写html标签,当然
我这个没有用到html标签,方法用到了正则来替换掉我不需要的东西,最终拼接成这样 /article/3.html
@helper PageList(string html,string controller, string action, string page) { string newHtml = Regex.Replace(html, @"(?<=""\/).*?(?:=)", controller + "/" + action + "/"); Regex reg = new Regex(@"(?<=\/)\d+"); newHtml = reg.Replace(newHtml, "$&.html"); //string newHtml = Regex.Replace(html, @"(?<="")\/.*?(?:=\d+)", "javascript:void(0);"); @Html.Raw(newHtml); }
下面就是是处理PagedListPager渲染后的html,直接调用上面的方法
@PageHelpers.PageList(Html.PagedListPager((IPagedList)Model, page => Url.Action(ViewContext.RouteData.Values["action"].ToString().Replace(".html", ""), new { page })).ToString(), ViewContext.RouteData.Values["controller"].ToString(), ViewContext.RouteData.Values["action"].ToString(), "1");
五、总结
这次pagedlist使用从刚开始的所搜到最后的使用,也学到了很多,
提供一下参考的文章
http://www.tuicool.com/articles/Bnm6fy
http://www.cnblogs.com/tangmingjun/archive/2012/05/30/2526301.html
http://www.bcnds.com/article/2015/6/1032.html
理解错误的,还请coder友多多指正!
文章含义模糊的,还请Coder友多多包含!
切磋问题的,还请coder友多多联系!
PS:NET/前端技术交流群 190293245