【譯】MVC3 20個秘方-(8)為列表結(jié)果分頁
問題
你有一個很龐大列表形式的結(jié)果,它加載的時間很長。或者你在這個很長的列表中不能很輕松的找到你的結(jié)果。把結(jié)果劃分成多個頁面將會減少頁面載入的時間并且?guī)湍愀斓恼业侥阆胍慕Y(jié)果,特別是結(jié)果已經(jīng)被排序的情況下。
解決方案
使用PagedList.MVC穿梭于各個記錄列表頁。
討論
為一個應(yīng)用程序分頁你需要通過NuGet Library安裝一個新的DLL“pagedList.MVC”。這將生成一個比完整的列表更好的分頁列表。選擇工具->Library Package Manager->Add Library Package Reference.在左邊選擇online 按鈕。在搜索框里輸入pagedList然后按下圖安裝PagedList.MVC:

一旦pagedlist安裝完成,創(chuàng)建分頁的代碼將被添加成為一個partial view。這允許以后為結(jié)果分頁時可以重用這個partial view。由于分頁的過程并沒有真正包含許多動態(tài)變量,所以這是一個完美的機會去重用這個HTML在每一個結(jié)果列表頁而帶來甚微的影響,同時保持外觀一致。
作為開始,展開Views 文件夾。右擊 Shared文件,選擇->添加->View。命名為_Paging,確定選著“Create as partial view”點擊添加。在新創(chuàng)建的view中添加如下代碼:
<p>
@if (Model.HasPreviousPage)
{
@Html.ActionLink("<< First", "Index", new
{
page = 1,
sortOrder = ViewBag.CurrentSortOrder
})
@Html.Raw(" ");
@Html.ActionLink("< Prev", "Index", new
{
page = Model.PageNumber - 1,
sortOrder =
ViewBag.CurrentSortOrder
})
}
else
{
@:<< First
@Html.Raw(" ");
@:< Prev
}
@if (Model.HasNextPage)
{
@Html.ActionLink("Next >", "Index", new
{
page = Model.PageNumber + 1,
sortOrder = ViewBag.CurrentSortOrder
})
@Html.Raw(" ");
@Html.ActionLink("Last >>", "Index", new
{
page = Model.PageCount,
sortOrder = ViewBag.CurrentSortOrder
})
}
else
{
@:Next >
@Html.Raw(" ")
@:Last >>
}
</p>
這個View 創(chuàng)建了4個link。首頁,前一頁,下一頁和末頁。我說有4個link是因為如果前邊沒有可用的頁面。那么前一頁和首頁的鏈接就是不可用的。每個link傳遞2個變量到Index()action。頁碼和當前排序的規(guī)則列。當前排序的規(guī)則列可以確保我分頁之后用戶也不會丟失他選擇的排序規(guī)則。
接下來,我們要在Book/Index 這個view上做一些更改:
@model PagedList.IPagedList<MvcApplication4.Models.Book>
<h2>@ViewBag.Title</h2>
<p>
@Html.ActionLink((string)ViewBag.CreateLink, "Create")
</p>
@Html.Partial("_Paging")
<table>
<tr>
<th>
@Html.ActionLink((string)ViewBag.TitleDisplay,
"Index", new { sortOrder = ViewBag.TitleSortParam })
</th>
<th>
@Html.ActionLink((string)ViewBag.IsbnDisplay,
"Index", new { sortOrder = ViewBag.IsbnSortParam })
</th>
<th>
@ViewBag.SummaryDisplay
</th>
<th>
@Html.ActionLink((string)ViewBag.AuthorDisplay,
"Index", new
{
sortOrder =
ViewBag.AuthorSortParam
})
</th>
<th>
@ViewBag.ThumbnailDisplay
</th>
<th>
@Html.ActionLink((string)ViewBag.PriceDisplay,
"Index", new { sortOrder = ViewBag.PriceSortParam })
</th>
<th>
@Html.ActionLink((string)ViewBag.PublishedDisplay,
"Index", new
{
sortOrder =
ViewBag.PublishedSortParam
})
</th>
<th>
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Isbn)
</td>
<td>
@Html.DisplayFor(modelItem => item.Summary)
</td>
<td>
@Html.DisplayFor(modelItem => item.Author)
</td>
<td>
@Html.DisplayFor(modelItem => item.Thumbnail)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Published)
</td>
<td>
@Html.ActionLink((string)ViewBag.EditLink,
"Edit", new { id = item.ID }) |
@Html.ActionLink((string)ViewBag.DetailsLink,
"Details", new { id = item.ID }) |
@Html.ActionLink((string)ViewBag.DeleteLink,
"Delete", new { id = item.ID })
</td>
</tr>
}
</table>
@Html.Partial("_Paging")
上邊的例子包含了對View的3個改變。第一,更新了model的type成強類型PagedList.IPagedList。
第二,_Paging partial view被引用了2次。一次在table上。一次在table下。這樣可以方便用戶點擊。
最后,要更新BookController。Index()這個 action 要被更新去接收一個新的參數(shù):page。并且用一個 paged List 去替換原來的返回值 list。并且,在sort order 塊中。添加一個新的 ViewBag變量 設(shè)置當前的sort order。代碼如下:
(譯者:我修改了原書中的代碼,因為這段代碼中有bug。ToChangedList接收的第一個參數(shù)不能為0,但是默認action傳入的page是1.這樣會引發(fā)異常):
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Dynamic;
using System.Web;
using System.Web.Mvc;
using MvcApplication.Models;
using MvcApplication.Utils;
using PagedList;
namespace MvcApplication.Controllers
{
public class BooksController : Controller
{
private BookDBContext db = new BookDBContext();
//
// GET: /Books/
public ViewResult Index(string sortOrder, int page = 1)
{
#region ViewBag Sort Params
ViewBag.CurrentSortOrder = sortOrder;
#endregion
const int maxRecords = 2;// maxRecords 是每頁的最大記錄數(shù)
var books = db.Books.OrderBy(sortOrder);
var currentPage = page <= 0 ? 1 : page;
return View(books.ToPagedList(currentPage,
maxRecords));
}
}
}
如果你想進一步擴展局部視圖(_Paging)重用在其他列表的結(jié)果,你只需要確保為每個列表設(shè)置相同的ViewBag。在這種情況下,列表結(jié)果
不在像這樣Index() action中。你可以更新Html.ActionLink調(diào)用另一個ViewBag變量定義的動作,使得它可能動態(tài)的使用。
另請參見

浙公網(wǎng)安備 33010602011771號