学习MVC分页,消化了一个别人的DEMO,基本上了解原理了。
原理
MVC分页,需要确定3个参数:
1、每一页的记录数量
2、当前的页码
3、记录总数
分页原理:
1、确定每一页的记录数量参数和总记录数量,计算出一共多少页(为了避免少计算页码,需要考虑总页数四舍五入。比如一页5条记录,如果21条记录,就会有5页,而不是4页。)
2、获得URL中的ID参数,确定当前页码
3、获得数据源,根据当前页码计算需要从数据源中取出多少条记录
4、生成分页条
5、在页面中显示分页条
代码
第一部分pagerHelper用于获取分页参数,并提供生成分页条的方法。
//分页的数据处理 public class PageHelper { #region 数据 public PagerHtml PageH; private int _pageSize,_totalCount, _currentPageIndex; /// <summary> /// 每页数据条数 /// </summary> public int PageSize { get { return _pageSize; } set { if (value < 1) throw new ArgumentOutOfRangeException(); _pageSize = value; CalcPage(); } } /// <summary> /// 总页数 /// </summary> public int PageCount { get; set; } /// <summary> /// 总条数 /// </summary> public int TotalCount { get { return _totalCount; } set { _totalCount = value; CalcPage(); } } #endregion 数据 #region 方法 public PageHelper() { } /// <summary> /// 初始化 /// </summary> /// <param name="pageSize">每页显示记录数量</param> /// <param name="currentPageIndex">页码</param> /// <param name="totalCount">记录总数</param> /// <param name="url">URL参数,用在HTML输出</param> public PageHelper(int pageSize, int currentPageIndex,int totalCount, string url) { this.PageSize = pageSize; this.CurrntPageIndex = currentPageIndex; this.TotalCount = totalCount; PageH = new PagerHtml(pageSize, currentPageIndex, totalCount, url, 8); } /// <summary> /// 当前页码 /// </summary> public int CurrntPageIndex { get { if (PageSize == 0 || PageCount == 0) return _currentPageIndex; if (_currentPageIndex < 1) return 1; else if (_currentPageIndex > PageCount) return PageCount; else return _currentPageIndex; } set { _currentPageIndex = value; if (_currentPageIndex < 1) _currentPageIndex = 1; } } /// <summary> /// 获取分页数据HTML /// </summary> /// <returns></returns> public string GetStr() { return PageH.GetStrClub(); } /// <summary> /// 重新计算当前页面总数 /// </summary> void CalcPage() { if (_pageSize == 0) return; PageCount = (int)Math.Ceiling(TotalCount * 1.0 / PageSize); } /// <summary> /// 返回当前页的记录起始索引 /// </summary> public int StartIndex { get { return (_currentPageIndex - 1) * PageSize; } } #endregion 方法 }
第二部分的代码用于生成分页条。和看的DEMO不一样,这里链接的URL是手动输入的,在DEMO里面是利用正则将页面的URL直接进行处理。
//分页栏的html输出 public class PagerHtml { #region 参数 public int PageSize { get; set; } public int CurrentPage { get; set; } public int RecordCount { get; set; } public int PageCount { get; set; } public string Url { get; set; } public int ExtendPage { get; set; } private string PageUnion { get; set; } #endregion 参数 #region 方法 /// <summary> /// 初始化 /// </summary> /// <param name="pagesize">页面尺寸</param> /// <param name="curPage">页码</param> /// <param name="recordCount">总数</param> /// <param name="url">网址</param> /// <param name="extendPage">显示的分页码数量</param> public PagerHtml(int pagesize, int curPage, int recordCount, string url, int extendPage) { PageUnion = ""; this.PageSize = pagesize; this.CurrentPage = curPage; this.RecordCount = recordCount; this.Url = url; this.ExtendPage = extendPage; PageCount = RecordCount % PageSize == 0 ? RecordCount / PageSize : (RecordCount / PageSize + 1);//避免少计算页码,这样比如一页5条记录,如果21条记录,就会有5页,而不是4页。 } /// <summary> /// 获取分页字符串 /// </summary> /// <returns></returns> public string GetStrClub() { //只有一页的情况 if (PageCount == 1 || RecordCount == 0) { return string.Empty; } int startPage = 1; int endPage = 1; int nextPage=CurrentPage + 1; int prePage=CurrentPage - 1; //格式化上一页,下一页链接 string t1 = "<a href=\"" + Url+"\\"+prePage.ToString()+ "\">上一页</a> "; string t2 = "<a href=\"" +Url+"\\"+nextPage.ToString()+ "\">下一页</a>"; if (PageCount < 1) PageCount = 1; if (ExtendPage < 3) ExtendPage = 2; if (PageCount > ExtendPage) { if (CurrentPage - (ExtendPage / 2) > 0) { if (CurrentPage + (ExtendPage / 2) < PageCount) { startPage = CurrentPage - (ExtendPage / 2); endPage = startPage + ExtendPage - 1; } else { endPage = PageCount; startPage = endPage - ExtendPage + 1; t2 = ""; } } else { endPage = ExtendPage; t1 = ""; } } else { startPage = 1; endPage = PageCount; t1 = ""; t2 = ""; } StringBuilder s = new StringBuilder(""); s.Append(t1); for (int i = startPage; i <= endPage; i++) { if (i == CurrentPage) { s.AppendFormat("{0}<div class=\"page_link\">", i); } else { s.AppendFormat("<a href=\"{0}\">{1}</a></div>",Url+"\\"+i.ToString(), i); } } s.Append(t2); return s.ToString(); } #endregion 方法 }
对数据源进行处理,只取分页显示的部分记录。
var q = value.AsQueryable<valModel>(); if (currentPage > 0) q = q.Skip((currentPage - 1) * pageSize); pagingSource = q.Take(pageSize).ToList();
model的完整代码:
TestModel
public class TestModel { public List<valModel> value; public List<valModel> pagingSource;//分页出来的数据 public PageHelper pager; public TestModel(string id) { int pageSize = 10; int currentPage; if (string.IsNullOrEmpty(id)) { currentPage = 1; } else { currentPage = Convert.ToInt16(id); } value = new List<valModel>(); //模拟数据源 for (int i = 0; i < 1000; i++) { valModel val = new valModel(i); value.Add(val); } int totalCount = value.Count; //分页 pagingSource = new List<valModel>(); var q = value.AsQueryable<valModel>(); if (currentPage > 0) q = q.Skip((currentPage - 1) * pageSize); pagingSource = q.Take(pageSize).ToList(); pager = new PageHelper(pageSize, currentPage, totalCount, "/home/catalog"); } } public class valModel { public string Value{get;set;} public valModel(int i) { Value = i.ToString(); } }
在view中显示:
TestView
<% website.Models.TestModel tm = ViewData.Model as website.Models.TestModel;%> <%foreach (var item in tm.pagingSource) { %> <tr> <td> <%=item.Value %> </td> </tr> <% } %> <div style="clear:both"></div> <%= tm.pager.GetStr()%>
contoler中的代码:
public ActionResult test(string id) { //id传递页码 Models.TestModel tm = new Models.TestModel(id); return View(tm); }
注意
1、这种不是ajax的
2、分页条的样式是可调的,用CSS即可。如果需要更多风格(如带省略号等),可以在pagehtml里面加点判断逻辑然后添加。
3、数据源是将所有记录全部取出后选择性的取其中一部分,如果数据量很大的话就很麻烦,其实也可以根据当前页和一页中的记录数量2个参数来即时取值,应该效果要好些。