在「ASP.NET MVC - 資料分頁(1) 使用MvcPaging」這篇文章中已經有介紹如何使用MvcPaging來做資料分頁,
而MvcPaging所提供的Html.Pager()所產生的分頁功能列是比較陽春的,
就是有各個頁數的連結以及上一頁、下一頁的連結,但有時候客戶那邊會希望分頁的功能列可以有些變化,
在不去修改MvcPaging原始碼的情況下,我們可以在IPagedList<T>的基礎上去自己設計一個分頁功能頁。
以下說明如何自訂分頁功能列(姑且命名為:MvcSimplePager)
2011-09-20 更新:
因為原來取名的SimplePager,已經有個jQuery Plugin也是同樣這個名字,所以就改為「MvcSimplePager」。
jQuery Plugin:「SimplePager - an easy jquery paging plugin」
Demo:http://geckohub.com/tests/simplepager/demo/2/
有興趣的人再去看看囉!
先來看看我們所做的MvcSimplePager呈顯的樣子。
上圖可以看到,將原本的用< , > 所代表的上頁、下頁給拿掉,取而代之的是第一頁、上一頁、下一頁、最後一頁,
並且在最後面顯示 當前頁、全部頁數、全部資料比數,而中間的頁數連結也希望可以使用參數的方式選擇是否出現。
下圖則是選擇不出現頁數連結的樣子。
一、建立PagerHelper.cs
建立一個靜態類別 PagerHelper,並且在類別中建立兩個靜態方法 MvcSimplePager,
第一個MvcSimplePager方法是預設不顯示頁數連結,
第二個則是主要的實作,另外提供是否顯示頁數連結的bool參數。
1: #region MvcSimplePager2:3: /// <summary>
4: /// 分頁Pager顯示
5: /// </summary>
6: /// <param name="html"></param>
7: /// <param name="pageSize">每頁顯示</param>
8: /// <param name="totalCount">總數據量</param>
9: /// <returns></returns>
10: public static string MvcSimplePager(this HtmlHelper html, int pageSize, int totalCount)11: {12: return MvcSimplePager(html, pageSize, totalCount, false);13: }14:15: /// <summary>
16: /// 分頁Pager顯示
17: /// </summary>
18: /// <param name="html">The HTML.</param>
19: /// <param name="pageSize">每頁顯示</param>
20: /// <param name="totalCount">總數據量</param>
21: /// <param name="showNumberLink">是否顯示數字連結.</param>
22: /// <returns></returns>
23: public static string MvcSimplePager(this HtmlHelper html, int pageSize, int totalCount, bool showNumberLink)24: {25: var queryString = html.ViewContext.HttpContext.Request.QueryString;26:27: //當前頁
28: int currentPage = 1;
29:30: //總頁數
31: var totalPages = Math.Max((totalCount + pageSize - 1) / pageSize, 1);32:33: //從ViewContext.RouteData.Values取得目前的RouteValueDictionary
34: var routeValueDict = new System.Web.Routing.RouteValueDictionary(html.ViewContext.RouteData.Values);
35:36: var _renderPager = new StringBuilder();
37:38: if (!string.IsNullOrEmpty(queryString[currentPageStr]))39: {40: //與相應的QueryString綁定
41: foreach (string key in queryString.Keys)42: {43: if (queryString[key] != null && !string.IsNullOrEmpty(key))44: {45: routeValueDict[key] = queryString[key];46: }47: }48: int.TryParse(queryString[currentPageStr], out currentPage);49: }50: else
51: {52: //取得 ~/Page/{page number} 的頁號參數
53: if (routeValueDict.ContainsKey(currentPageStr))
54: {55: int.TryParse(routeValueDict[currentPageStr].ToString(), out currentPage);56: }57: }58:59: //保留查詢字元到下一頁
60: foreach (string key in queryString.Keys)61: {62: routeValueDict[key] = queryString[key];63: }64:65: if (currentPage <= 0)
66: {67: currentPage = 1;68: }69:70: string emptyAtagFormat = "<a href=\"#\" style=\"cursor:pointer;\">{0}</a>";71:72: if (totalPages == 1)
73: {74: _renderPager.AppendFormat(emptyAtagFormat, "第一頁");
75: _renderPager.AppendFormat(emptyAtagFormat, "上一頁");
76: _renderPager.AppendFormat(emptyAtagFormat, "下一頁");
77: _renderPager.AppendFormat(emptyAtagFormat, "最後一頁");
78: }79: else if (totalPages > 1)80: {81: if (currentPage != 1)
82: {83: //處理首頁連接
84: routeValueDict[currentPageStr] = 1;85: _renderPager.Append(html.RouteLink("第一頁", routeValueDict));
86: }87: else
88: {89: _renderPager.AppendFormat(emptyAtagFormat, "第一頁");
90: }91:92: if (currentPage > 1)
93: {94: //處理上一頁的連接
95: routeValueDict[currentPageStr] = currentPage - 1;96: _renderPager.Append(html.RouteLink("上一頁", routeValueDict));
97: }98: else
99: {100: _renderPager.AppendFormat(emptyAtagFormat, "上一頁");
101: }102:103: #region 顯示頁數連結104: if (showNumberLink)
105: {106: var pageCount = (int)Math.Ceiling(totalCount / (double)pageSize);107: const int nrOfPagesToDisplay = 10;108:109: var start = 1;110: var end = pageCount;111:112: if (pageCount > nrOfPagesToDisplay)
113: {114: var middle = (int)Math.Ceiling(nrOfPagesToDisplay / 2d) - 1;
115: var below = (currentPage - middle);116: var above = (currentPage + middle);117:118: if (below < 4)
119: {120: above = nrOfPagesToDisplay;121: below = 1;122: }123: else if (above > (pageCount - 4))124: {125: above = pageCount;126: below = (pageCount - nrOfPagesToDisplay);127: }128:129: start = below;130: end = above;131: }132:133: if (start > 3)
134: {135: routeValueDict[currentPageStr] = "1";
136: _renderPager.Append(html.RouteLink("1", routeValueDict));
137:138: routeValueDict[currentPageStr] = "2";
139: _renderPager.Append(html.RouteLink("2", routeValueDict));
140:141: _renderPager.Append("...");
142: }143:144: for (var i = start; i <= end; i++)
145: {146: if (i == currentPage || (currentPage <= 0 && i == 0))
147: {148: _renderPager.AppendFormat("<span class=\"current\">{0}</span>", i);
149: }150: else
151: {152: routeValueDict[currentPageStr] = i.ToString();153: _renderPager.Append(html.RouteLink(i.ToString(), routeValueDict));154: }155: }156: if (end < (pageCount - 3))
157: {158: _renderPager.Append("...");
159:160: routeValueDict[currentPageStr] = (pageCount - 1).ToString();161: _renderPager.Append(html.RouteLink((pageCount - 1).ToString(), routeValueDict));162:163: routeValueDict[currentPageStr] = pageCount.ToString();164: _renderPager.Append(html.RouteLink(pageCount.ToString(), routeValueDict));165: }166: }167: #endregion168:169: if (currentPage < totalPages)
170: {171: //處理下一頁的連結
172: routeValueDict[currentPageStr] = currentPage + 1;173: _renderPager.Append(html.RouteLink("下一頁", routeValueDict));
174: }175: else
176: {177: _renderPager.AppendFormat(emptyAtagFormat, "下一頁");
178: }179:180: if (currentPage != totalPages)
181: {182: routeValueDict[currentPageStr] = totalPages;183: _renderPager.Append(html.RouteLink("最後一頁", routeValueDict));
184: }185: else
186: {187: _renderPager.AppendFormat(emptyAtagFormat, "最後一頁");
188: }189: }190:191: // 目前頁數/總頁數
192: _renderPager.AppendFormat(" 第 {0} 頁 / 共 {1} 頁 共 {2} 筆", currentPage, totalPages, totalCount);
193:194: return _renderPager.ToString();
195: }196:197: #endregion
在上面的程式碼中,比較重要的地方在於RouteValueDictionary的使用
第38行,建立一個routeValueDict物件,從ViewContent.RouteData.Value取得RouteValueDictionary的內容,
var routeValueDict = new System.Web.Routing.RouteValueDictionary(html.ViewContext.RouteData.Values);
取出RouteValueDictionary則是為了要產生在分頁功能列中每個連結裡的HyperLink
然後在每個要產生有效連結的地方,還要去設定routeValueDict[“page”] ( routeValueDict[currentPageStr] )
這是要設定每個連結的HyperLink中的page參數,設定正確的頁數,
而設定連結的HyperLink則是使用了 Html LinkExtensions 的 RouteLink()方法
MSDN - Html LinkExtensions.RouteLink() 方法
MSDN - LinkExtensions.RouteLink 方法 (HtmlHelper, String, RouteValueDictionary)
而位在Line:104的地方,就是判斷 showNumberLink 參數已決定是否顯示頁數連結,
而這中間產生頁數連結的程式部分則是直接取用MvcPaging的Pager()裡面的程式,
而有修改的地方就是產生HtperLink的部份。
好的,MvcSimplePager()方法已經準備就緒,接下來就是直接使用。
二、Controller, Action
在Controller的Action內容部分是不會有所變化
#region PageMethod2/// <summary>
/// Pages the method2.
/// </summary>
/// <param name="page">The page.</param>
/// <returns></returns>
public ActionResult PageMethod2(int? page){int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
var result = this.productService.GetCollection();
return View(result.ToPagedList(currentPageIndex, 5));
}#endregion
三、ViewPage
ViewPage的部份則是延續「ASP.NET MVC - 資料分頁(1) 使用MvcPaging」中對於ViewPage的設定,
而MvcSimplePager的使用上有以下幾種方式
1.這是預設不會顯示頁數連結
<div class="pager"><%= Html.MvcSimplePager(Model.PageSize, Model.TotalItemCount)%></div>
2.這是另一種不會顯示頁數連結的使用方式
<div class="pager"><%= Html.MvcSimplePager(Model.PageSize, Model.TotalItemCount, false)%></div>
3.顯示頁數連結
<div class="pager"><%= Html.MvcSimplePager(Model.PageSize, Model.TotalItemCount, true)%></div>
可以看到,在Controller/Action中沒有需要改變的地方,而在ViewPage裡需要變動的地方也相當少,
與原來MvcPaging Pager()做個比較:
<div class="pager"><%= Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount) %></div>
頂多就只是方法名稱不一樣,且又多了另一種顯示方式的選擇。
最後再來看看顯示的畫面:
第一頁
中間頁數顯示
最後一頁
這裡說明了如何以MvcPaging為基礎,讓我們自訂頁面上的分頁功能列,
所以客戶那邊對於分頁功能列想要什麼樣的變化,對我們來說就不是一件困難的事啦!
下篇「資料分頁-使用MvcPaging」的文章,再來討論如何在有查詢表單下依然可以使用資料分頁的作法,
因為現在介紹的兩篇資料分頁的文章,最後的結果都是使用HyperLink的方式將頁數資料傳回後端,
再把指定頁數的分頁傳回到前端,因為是用HyperLink的方式,所以表單上的查詢條件就無法保存,
甚至傳回前端的分頁資料也不是符合查詢條件的資料了。
以上。
大大你好~我又來打擾了
回覆刪除請問大大做的這篇也可以把它應用成Ajax的方式嗎?
如果你有看過這部落格的「資料分頁」系列文章,你將會有發現的...
刪除「資料分頁」系列的文章有兩個範例文章下載,
請將程式下載後再依照文章內容來看程式,這樣才會有所收穫。
另外一個建議,學習一項技術或是技巧,不要太追求片面的內容,
真的建議你要有系統的做學習,而不是跳著看然後只挑想要的來用,
如果你有認真找資料的話,
「ASP.NET MVC - 資料分頁(4) MvcSimplePostPager + AJAX」
這一篇就是你所要的!!!
回覆大大
回覆刪除其實您這篇ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.4:分頁進階處理
才是我想要的資料
只是我想一步步作
1.由最單純的分頁加上Ajax
2.加上條件search部份資料加上Ajax
3.由以上的加上排序作Ajax
感謝大大的建議~^^