在各式各樣的網站中,Data Grid是很常見的功能,將資料庫裡符合查詢條件的資料逐筆列出,但是當資料筆數太多時,一次Show在同一個頁面上不僅頁面的Scroll Bar會拉到死,在那之前要撈出那多資料整個網頁都Hang住了,為了解決這個問題才有Paging這個技巧。
Paging的原理其實就是在SQL Select語法上下功夫,將整個查詢結果根據PageSize(一頁顯示最多筆數), TotalCount(資料總筆數)進行分割,在靠PageIndex(分頁索引)去取得範圍內的資料。使用Entity Framework可以利用Take, Skip...等方法來實作Paging,在ASP.NET MVC就可以搭配使用Entity Framework。然而,像限量這麼懶的人當然有現成就找現成的來用,限量在NuGet就找到一套MvcPaging的套件,作者已經將Paging實作成一個元件,只要將該丟的東西丟進去就有Paging功能了,接下來限量就來介紹如何使用MvcPaging這套Paging套件。
首先,到NuGet搜尋MvcPaging安裝。
接著,因為我們要用Ajax來進行Paging的動作,所以要額外安裝並加入Jquery ajax的Library。
在Controller裡建立頁面的Action,因為限量要用Ajax來Paging,所以Action要建兩個,ProjectManage為主頁面的Action,一開始會先把第一頁的資料撈出來;ProjectList為Ajax GET呼叫取得該分頁資料的Action,因為要用Ajax改變Data Grid,所以要用PartialView。
PTMController.cs
在ProjectList接收到page(分頁號碼)後,先將page轉為index(PageIndex)值,PageIndex與PageNumber的關係差別在於PageIndex起始為0而PageNumber起始為1。接著'使用Entity Framework _db.Project取得所有資料再轉成PagedList並傳入PartialView中。
ProjectManage.cshtml為主頁面,內含有_ProjectList PartialView,在初始接收到第一頁的資料時會透過Html.Partial將第一頁的Model傳入_ProjectList頁面。
ProjectManage.cshtml
_ProjectList.cshtml為Data Grid Paging的PartialView,這裡將Model的資料逐筆列出,這裡要注意的是,因為限量要用讓程式自動去取得該欄位名稱,所以讓這個頁面去繼承IEnumerable<>,這樣才可以使用Html.DisplayNameFor,不然Html.DisplayNameFor是不支援IPagedList<>,但IPagedList<>是繼承IEnumerable<>的,所以限量在後面將Model轉型為IPagedList<>,這樣後續使用才不會有問題。Paging一般分為兩個部分,一為Show資料的Data Grid,另一為Pager,Pager就是切換資料頁的元件,MvcPaging把Pager寫成一個Html擴充元件,直接使用Html.Pager()並丟入Model的PageSize, PageNumber, TotalItemCount就OK了,如果是Ajax的話就要再丟一個AjaxOption,指定欲更新Data Grid的ID與對應的Action即可。
_ProjectList.cshtml
在_ProjectList.cshtml的Pager裡,限量多加了DisplayTemplate, MaxNrOfPages,這是MvcPaging所提供的貼心設計,MaxNrOfPages設定的數字代表的是Pager從初始往後顯示的Paging Link數量,例如在上面限量設定為四,結果會顯示<< 1 2 3 4 ... 6 >>,因為最後一頁會顯示,所以總和會是1(<<) + 4(1, 2, 3, 4) + 1(...) + 1(6) + 1(>>) = 8。DisplayTemplate是讓開發人員能夠客製化Pager樣式的選項,作者將客製化Pager部分轉換成PartialView,所以要建立一個Pager的PartialView,這裡要注意的是,程式會去尋找DisplayTemplates目錄底下的Pager PartialView,限量認為這PartialView要放在Share底下,所以在Share底下建立一個DisplayTemplates資料夾,將客製化的Pager PartialView放在此。
_BootstrapPagingTemplate.cshtml
_BootstrapPagingTemplate.cshtml為參考官網的範例,此範例使用TagBuilder依據相關條件產生出Bootstrap樣式的Pager。
執行結果:
這樣就簡單快速完成MVC上的Paging功能,但一直用現成的東西卻不搞懂原理是很難進步的,所以建議使用歸使用,有空還是得要去看看實作的原理。
參考來源:
GitHub - MvcPaging
Paging的原理其實就是在SQL Select語法上下功夫,將整個查詢結果根據PageSize(一頁顯示最多筆數), TotalCount(資料總筆數)進行分割,在靠PageIndex(分頁索引)去取得範圍內的資料。使用Entity Framework可以利用Take, Skip...等方法來實作Paging,在ASP.NET MVC就可以搭配使用Entity Framework。然而,像限量這麼懶的人當然有現成就找現成的來用,限量在NuGet就找到一套MvcPaging的套件,作者已經將Paging實作成一個元件,只要將該丟的東西丟進去就有Paging功能了,接下來限量就來介紹如何使用MvcPaging這套Paging套件。
首先,到NuGet搜尋MvcPaging安裝。
接著,因為我們要用Ajax來進行Paging的動作,所以要額外安裝並加入Jquery ajax的Library。
在Controller裡建立頁面的Action,因為限量要用Ajax來Paging,所以Action要建兩個,ProjectManage為主頁面的Action,一開始會先把第一頁的資料撈出來;ProjectList為Ajax GET呼叫取得該分頁資料的Action,因為要用Ajax改變Data Grid,所以要用PartialView。
PTMController.cs
public class PTMController : Controller { PTMDBEntities _db = new PTMDBEntities(); // GET: PTM public ActionResult Index() { return View(); } public ActionResult ProjectManage() { var projs = _db.Project.ToList().ToPagedList( 0, 5 ); return View(projs); } public ActionResult ProjectList(int? page) { var index = page.HasValue ? page.Value - 1 : 0; var projs = _db.Project.ToList().ToPagedList( index, 5); return PartialView( "_ProjectList", projs ); } }
在ProjectList接收到page(分頁號碼)後,先將page轉為index(PageIndex)值,PageIndex與PageNumber的關係差別在於PageIndex起始為0而PageNumber起始為1。接著'使用Entity Framework _db.Project取得所有資料再轉成PagedList並傳入PartialView中。
ProjectManage.cshtml為主頁面,內含有_ProjectList PartialView,在初始接收到第一頁的資料時會透過Html.Partial將第一頁的Model傳入_ProjectList頁面。
ProjectManage.cshtml
@model IEnumerable<WebApplication.Models.Project> @{ ViewBag.Title = "ProjectManage"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>ProjectManage</h2> <div id="proj_list_container"> @Html.Partial( "_ProjectList", Model ) </div>
_ProjectList.cshtml為Data Grid Paging的PartialView,這裡將Model的資料逐筆列出,這裡要注意的是,因為限量要用讓程式自動去取得該欄位名稱,所以讓這個頁面去繼承IEnumerable<>,這樣才可以使用Html.DisplayNameFor,不然Html.DisplayNameFor是不支援IPagedList<>,但IPagedList<>是繼承IEnumerable<>的,所以限量在後面將Model轉型為IPagedList<>,這樣後續使用才不會有問題。Paging一般分為兩個部分,一為Show資料的Data Grid,另一為Pager,Pager就是切換資料頁的元件,MvcPaging把Pager寫成一個Html擴充元件,直接使用Html.Pager()並丟入Model的PageSize, PageNumber, TotalItemCount就OK了,如果是Ajax的話就要再丟一個AjaxOption,指定欲更新Data Grid的ID與對應的Action即可。
_ProjectList.cshtml
@model IEnumerable<WebApplication.Models.Project> @{ var pagedlist = (IPagedList)Model; } <table class="table"> <thead> <tr> <th>@Html.DisplayNameFor(model => model.Name)</th> <th>@Html.DisplayNameFor( model => model.Description )</th> <th>@Html.DisplayNameFor( model => model.StartTime )</th> <th>@Html.DisplayNameFor( model => model.EndTime )</th> </tr> </thead> <tbody> @foreach ( var modelItem in Model ) { <tr> <td>@modelItem.Name</td> <td>@modelItem.Description</td> <td>@modelItem.StartTime</td> <td>@modelItem.EndTime</td> </tr> } </tbody> </table> <div style="text-align:center"> @Html.Pager( pagedlist.PageSize, pagedlist.PageNumber, pagedlist.TotalItemCount, new AjaxOptions { UpdateTargetId = "proj_list_container" } ).Options( o => o.Action( "ProjectList" ).DisplayTemplate( "_BootstrapPagingTemplate" ) .MaxNrOfPages( 4 ) ) </div>
在_ProjectList.cshtml的Pager裡,限量多加了DisplayTemplate, MaxNrOfPages,這是MvcPaging所提供的貼心設計,MaxNrOfPages設定的數字代表的是Pager從初始往後顯示的Paging Link數量,例如在上面限量設定為四,結果會顯示<< 1 2 3 4 ... 6 >>,因為最後一頁會顯示,所以總和會是1(<<) + 4(1, 2, 3, 4) + 1(...) + 1(6) + 1(>>) = 8。DisplayTemplate是讓開發人員能夠客製化Pager樣式的選項,作者將客製化Pager部分轉換成PartialView,所以要建立一個Pager的PartialView,這裡要注意的是,程式會去尋找DisplayTemplates目錄底下的Pager PartialView,限量認為這PartialView要放在Share底下,所以在Share底下建立一個DisplayTemplates資料夾,將客製化的Pager PartialView放在此。
_BootstrapPagingTemplate.cshtml
@model PaginationModel <ul class="pagination"> @foreach ( var link in Model.PaginationLinks ) { @BuildLink( link ) } </ul> @helper BuildLink( PaginationLink link ) { var liBuilder = new TagBuilder( "li" ); if ( link.IsCurrent ) { liBuilder.MergeAttribute( "class", "active" ); } if ( !link.Active ) { liBuilder.MergeAttribute( "class", "disabled" ); } var aBuilder = new TagBuilder( "a" ); if ( link.Url == null ) { aBuilder.MergeAttribute( "href", "#" ); } else { aBuilder.MergeAttribute( "href", link.Url ); } // Ajax support if ( Model.AjaxOptions != null ) { foreach ( var ajaxOption in Model.AjaxOptions.ToUnobtrusiveHtmlAttributes() ) { aBuilder.MergeAttribute( ajaxOption.Key, ajaxOption.Value.ToString(), true ); } } if ( link.DisplayText == "«" ) { aBuilder.InnerHtml = "«"; } else if ( link.DisplayText == "»" ) { aBuilder.InnerHtml = "»"; } else { aBuilder.SetInnerText( link.DisplayText ); } liBuilder.InnerHtml = aBuilder.ToString(); @Html.Raw( liBuilder.ToString() ) }
_BootstrapPagingTemplate.cshtml為參考官網的範例,此範例使用TagBuilder依據相關條件產生出Bootstrap樣式的Pager。
執行結果:
這樣就簡單快速完成MVC上的Paging功能,但一直用現成的東西卻不搞懂原理是很難進步的,所以建議使用歸使用,有空還是得要去看看實作的原理。
參考來源:
GitHub - MvcPaging
留言
張貼留言