這幾天接連好幾篇介紹 MvcPaging 2.0 的應用,從一般的分頁、AJAX 分頁,最後是使用 jQuery 的 AJAX 分頁,幾乎都把 MvcPaging 2.0 的基本應用都給介紹完了,但其實還有一樣沒有介紹,那就是自訂分頁樣式,這是 MvcPagin 2.0 的一個新功能「DisplayTemplate」,我們可以設定一個 Template 的 PartialView,這個 PartialView 是用來產生 Pager,而產生 Pager 的方法則是使用寫在 View Page 上面的 Razor @helper,有別於以往產生 Pager 內容是必須要從後端的方式,在前端使用 Razor @helper 來產生 Pager 會更為容易。
回顧一下,之前我們如果想要依據需求去客製分頁列的樣式時,我們是需要在後端去新增一個 Method,由這個 Method 來產生 Pager 內容,
這個我在以前的文章有做作過介紹:
ASP.NET MVC - 資料分頁(2) 自訂分頁功能列 MvcSimplePager
ASP.NET MVC - 資料分頁(3) 自訂分頁功能列 MvcSimplePostPager
在後端的 Method 去產生一個客製 Pager,其實不是那麼容易,所以當分頁有比較特殊的需求要解決時,就會比較麻煩,所以 MvcPaging 2.0 就利用了 ASP.NET MVC 3 Razor 的一個功能「Razor @helper」來解決這樣的問題,什麼是「Razor @helper」呢?這邊不多做說明,而是提供幾篇文章的連結,讓大家有個概念與了解,
ScottGu’s Blog - ASP.NET MVC 3 and the @helper syntax within Razor
ScottGu的中文部落格 - ASP.NET MVC 3和Razor中的@helper 語法
天空的垃圾場 - ASP.NET MVC – Razor的@helper語法
其實在 twMVC 第一場的研討會中也曾經由 Dino 介紹過 Razor @helper,
活動詳細資訊「 twMVC - 2012_04_26 與 ASP.NET MVC 的第一次親密接觸 」
接下來就來說明如何使用 DisplayTemplate 以顯示並使用客製的 Pager 樣式內容,這邊的程式範本是使用「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.4:分頁進階處理」(PagedAjax2),各位可以到「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 - 範例程式下載」裡去下載範例程式。
複製 PagedAjax2 的程式內容,並且另外建立一個新的 Action 方法,
#region -- PagedTemplate --
public ActionResult PagedTemplate()
{
int currentPageIndex = 0;
this.PrepareDropDownLists(this.FilterCity, this.SortColumnName, this.SortType);
this.SearchSolumnDropDownList(string.Empty);
ViewData.Model = this.allCustomers.ToPagedList(currentPageIndex, DefaultPageSize);
return View();
}
public ActionResult PagedTemplatePartial(int? page,
string keyword,
string searchColumn,
string city = "all",
string sortColumnName = "CustomerID",
string sort = "asc")
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
this.FilterCity = city;
this.SortColumnName = sortColumnName;
this.SortType = sort;
ViewBag.Keyword = keyword;
ViewBag.DisplaySortColumnLink = new Func<string, MvcHtmlString>(SortColumnLink);
using (NorthwindEntities db = new NorthwindEntities())
{
var query = db.Customers.Select(x => x);
if (!string.IsNullOrWhiteSpace(keyword))
{
string queryExpression = string.Format("{0}.Contains(@0)", searchColumn);
query = query.Where(queryExpression, keyword);
}
if (!city.Equals("all"))
{
query = query.Where("City == @0", city ?? "London");
}
query = query.OrderBy(string.Format("{0} {1}", sortColumnName, sort));
ViewData.Model = query.ToPagedList(currentPageIndex, DefaultPageSize);
}
return PartialView("_PagedTemplate");
}
#endregion
分別建立好 View Page 以及 PartialView Page
「PagedTemplate.cshtml」
@model IPagedList<MvcMSSQL.Models.Customer>
@{
ViewBag.Title = "Advanced - PagedAjax - DisplayTemplated";
Layout = "~/Views/Shared/_LayoutTemplate.cshtml";
}
<h2>Advanced - PagedAjax - DisplayTemplated</h2>
<fieldset>
<br />
City:@ViewData["CityDDL"]
Saerch Column:@ViewData["SearchColumnDDL"]
Contains <input type="text" id="keyword" name="keyword" value="@ViewBag.Keyword" />
<input type="hidden" id="sortColumnName" value="CustomerID" />
<input type="hidden" id="sort" value="asc" />
<input type="button" value="Submit" id="ButtonSubmit" />
<input type="button" value="Reset" id="ButtonReset" />
</fieldset>
<div id="gridcontainer">
</div>
@if (false){ <script src="../../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script> }
<script type="text/javascript">
<!--
$(document).ready(function () {
$('#ButtonSubmit').click(function () { ButtonSubmitEventHandler(); });
$('#ButtonReset').click(function () { ButtonResetEventHandler(); });
});
function ButtonResetEventHandler() {
$('#city').removeAttr('disabled');
$('#searchColumn').removeAttr('disabled');
$('#searchColumn option:eq(0)').attr('selected', true);
$('#keyword').removeAttr('disabled').val('');
$('#sortColumnName').val('CustomerID');
$('#sort').val('asc');
$('#gridcontainer').empty();
}
function ButtonSubmitEventHandler() {
var cityValue = $('#city option:selected').val();
var searchColumnValue = $('#searchColumn option:selected').val();
var keywordValue = $.trim($('#keyword').val());
var sortColumnValue = $('#sortColumnName').val();
var sortValue = $('#sort').val();
$.ajax({
url: '@Url.Action("PagedTemplatePartial", "Advanced")',
data: { keyword: keywordValue, searchColumn: searchColumnValue, city: cityValue, sortColumnName: sortColumnValue, sort: sortValue },
type: 'post',
async: false,
cache: false,
dataType: 'html',
success: function (data) {
$('#gridcontainer').html(data);
$('#city').attr('disabled', true);
$('#sortColumnName').attr('disabled', true);
$('#sort').attr('disabled', true);
$('#searchColumn').attr('disabled', true);
$('#keyword').attr('disabled', true);
}
});
}
function postPage(page) {
var cityValue = $('#city option:selected').val();
var searchColumnValue = $('#searchColumn option:selected').val();
var keywordValue = $.trim($('#keyword').val());
var sortColumnValue = $('#sortColumnName').val();
var sortValue = $('#sort').val();
$.ajax({
url: '@Url.Action("PagedTemplatePartial", "Advanced")',
data: { page: page, keyword: keywordValue, searchColumn: searchColumnValue, city: cityValue, sortColumnName: sortColumnValue, sort: sortValue },
type: 'post',
async: false,
cache: false,
dataType: 'html',
success: function (data) {
$('#gridcontainer').html(data);
$('#city').attr('disabled', true);
$('#sortColumnName').attr('disabled', true);
$('#sort').attr('disabled', true);
$('#searchColumn').attr('disabled', true);
$('#keyword').attr('disabled', true);
}
});
};
-->
</script>
「_PagedTemplate.cshtml」
@model PagedList<MvcMSSQL.Models.Customer>
@if (Model != null && Model.Count > 0)
{
<div class="pager">
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.DisplayTemplate("PagerTemplate")
.MaxNrOfPages(10))
| 第 @Model.PageNumber 頁 / 共 @Model.PageCount 頁 | 顯示第 @Model.ItemStart - @Model.ItemEnd 項資料 / 共 @Model.TotalItemCount 項 |
</div>
<br />
<table>
<thead>
<th>
@ViewBag.DisplaySortColumnLink("CompanyName")
</th>
<th>
@ViewBag.DisplaySortColumnLink("ContactName")
</th>
<th>
@ViewBag.DisplaySortColumnLink("ContactTitle")
</th>
<th>
@ViewBag.DisplaySortColumnLink("Address")
</th>
<th>
@ViewBag.DisplaySortColumnLink("City")
</th>
<th>
@ViewBag.DisplaySortColumnLink("Region")
</th>
<th>
@ViewBag.DisplaySortColumnLink("PostalCode")
</th>
<th>
@ViewBag.DisplaySortColumnLink("Country")
</th>
<th>
@ViewBag.DisplaySortColumnLink("Phone")
</th>
<th>
@ViewBag.DisplaySortColumnLink("Fax")
</th>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>
@item.CompanyName
</td>
<td>
@item.ContactName
</td>
<td>
@item.ContactTitle
</td>
<td>
@item.Address
</td>
<td>
@item.City
</td>
<td>
@item.Region
</td>
<td>
@item.PostalCode
</td>
<td>
@item.Country
</td>
<td>
@item.Phone
</td>
<td>
@item.Fax
</td>
</tr>
}
</tbody>
</table>
}
@if (false)
{ <script src="../../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script> }
<script type="text/javascript">
$(document).ready(function () {
$('.pager> a').each(function (i, item) {
if ($(item).attr('href') != '#'){
var page = $(item).attr('href').replace('@(Url.Action("PagedTemplatePartial", "Advanced"))?page=', '');
$(item).attr('href', '#').click(function () { postPage(page); });
}
});
$('[class="sortColumnLink"]').each(function (i, item) {
var sortColumnName = $(item).attr('href');
var sortType = $(item).attr('id').replace(sortColumnName + "_", "");
var currentStyle = $(item).attr('style');
if ($.trim(currentStyle).length > 0) {
sortType = sortType == 'asc' ? 'desc' : 'asc';
}
$(item).attr('href', '#').click(function () {
$('#sortColumnName').val(sortColumnName);
$('#sort').val(sortType);
ButtonSubmitEventHandler();
});
});
});
</script>
在「_PagedTemplate.cshtml」中要注意到的是 pager 的內容設定,
<div class="pager">@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o.DisplayTemplate("PagerTemplate").MaxNrOfPages(10))| 第 @Model.PageNumber 頁 / 共 @Model.PageCount 頁 | 顯示第 @Model.ItemStart - @Model.ItemEnd 項資料 / 共 @Model.TotalItemCount 項 |</div>
在 Html.Pager() 的 Oprions 設定內容裡,我們在 DisplayTemplate() 中指定了一個 Template 的 PartialView,另外也有設定了 MaxNrOrPages(),其值為 10,「MaxNrOrPages」這可以讓我們設定每次分頁最多可以顯示幾頁,而如果沒有設定 MaxNrOrPages() 的話,預設值本身就是為 10。
DisplayTemplate 的 PartialView 內容
這個 Template 的 PartialView 檔案可以建立在 Views > Shared 目錄下,必須建立一個目錄「DisplayTemplate」(只能使用這個目錄名稱),然後再把 Pager 的 Template PartialView 檔案放在底下,
其實也可以把這個 DisplayTemplates 的目錄與檔案放在 Controller 所對應的 Views 子目錄下,但因為這個 Template 檔案會是屬於與其他 Controller 與 View Page 可以共用的,所以還是建議放在「Views > Shared」目錄下會比較好。
接下來就看這個 Template Partial View 檔案的內容,
「Views > Shared > DisplayTemplate > PagerTemplate.cshtml」
1: @model PaginationModel 2: 3: @BuildFirstLink() 4: 5: @foreach (var link in Model.PaginationLinks) 6: { 7: @BuildLink(link) 8: } 9: 10: @BuilderLastLink() 11: 12: 13: @helper BuildFirstLink() 14: { 15: if (Model.PaginationLinks.Count > 0) 16: { 17: <a href="1">最前頁</a> 18: } 19: } 20: 21: @helper BuilderLastLink() 22: { 23: if (Model.PaginationLinks.Count > 0) 24: { 25: <a href="@Html.Raw(Model.PaginationLinks.Count.ToString())">最後頁</a> 26: } 27: } 28: 29: @helper BuildLink(PaginationLink link) 30: { 31: var aBuilder = new TagBuilder("a"); 32: if (link.Url == null) 33: { 34: aBuilder.MergeAttribute("href", "#"); 35: } 36: else 37: { 38: aBuilder.MergeAttribute("href", link.Url); 39: } 40: 41: if (link.IsCurrent) 42: { 43: aBuilder.MergeAttribute("class", "current"); 44: } 45: 46: if (link.DisplayText == "«") 47: { 48: aBuilder.SetInnerText("上一頁"); 49: @Html.Raw(aBuilder.ToString()) 50: } 51: else if (link.DisplayText == "»") 52: { 53: aBuilder.SetInnerText("下一頁"); 54: @Html.Raw(aBuilder.ToString()) 55: } 56: else if (link.DisplayText == "...") 57: { 58: @Html.Raw(" ... ") 59: } 60: else 61: { 62: aBuilder.SetInnerText(link.DisplayText); 63: @Html.Raw(aBuilder.ToString()) 64: } 65: } |
「PagerTemplate.cshtml」就是使用了 Razor @helper 來產生 Pager 的分頁連結內容,程式內容我就不再贅述,很淺白的程式內容,相信大家都可以了解。
最後就來看看程式執行的結果吧!
一開始的執行畫面
顯示資料內容與 Pager 內容
在下面兩張圖所框起來的部分,這是要說明「MaxNrOrPages」的設定所產生的結果,
如果是分頁碼是在全部頁數的中間的話,則是產生如下圖的樣式,不會超過 10 個分頁連結,
這一篇文章說明 MvcPaging 2.0 所提供的 DisplayTemplate 功能,讓我們可以客製 Pager 的顯示樣式與內容。
參考連結
github – MvcPaging
https://github.com/martijnboland/MvcPaging
以上
沒有留言:
張貼留言