昨天,我的人生朝一个方向前进;而今天却朝着另一个方向。昨天,我相信我不可能做的事;今天,我却做了。
项目结构:
实体类:
public class Product
{
public string Name { get ; set ; }
public string Category { get ; set ; }
}
public class SearchModel
{
public SearchModel ()
{
page = 1 ;
}
public int ? page { get ; set ; }
}
public class ViewByCategoriesViewModel
{
public IPagedList<Product> Products { get ; set ; }
public string [] AvailableCategories { get ; set ; }
public string [] Categories { get ; set ; }
}
public class ViewSourceViewModel
{
public string RazorCode { get ; set ; }
public string ControllerCode { get ; set ; }
}
Controllers文件夹中控制器类
[HandleError]
public class HomeController : Controller
{
public ActionResult Index ()
{
return View();
}
public ActionResult About ()
{
return View();
}
}
public class PagingController : Controller
{
private const int DefaultPageSize = 10 ;
private readonly string [] allCategories = new string [3 ] {"Shoes" , "Electronics" , "Food" };
private readonly IList<Product> allProducts = new List<Product>();
public PagingController ()
{
InitializeProducts();
}
private void InitializeProducts ()
{
for (int i = 0 ; i < 527 ; i++)
{
var product = new Product();
product.Name = "Product " + (i + 1 );
int categoryIndex = i%4 ;
if (categoryIndex > 2 )
{
categoryIndex = categoryIndex - 3 ;
}
product.Category = allCategories[categoryIndex];
allProducts.Add(product);
}
}
public ActionResult Index (int ? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
return View(allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}
public ActionResult CustomPageRouteValueKey (SearchModel search)
{
int currentPageIndex = search.page.HasValue ? search.page.Value - 1 : 0 ;
return View(allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}
public ActionResult ViewByCategory (string categoryName, int ? page)
{
categoryName = categoryName ?? allCategories[0 ];
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
IPagedList<Product> productsByCategory =
allProducts.Where(p => p.Category.Equals(categoryName)).ToPagedList(currentPageIndex,
DefaultPageSize);
ViewBag.CategoryName = new SelectList(allCategories, categoryName);
ViewBag.CategoryDisplayName = categoryName;
return View("ProductsByCategory" , productsByCategory);
}
public ActionResult ViewByCategories (string [] categories, int ? page)
{
var model = new ViewByCategoriesViewModel();
model.Categories = categories ?? new string [0 ];
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
model.Products = allProducts.Where(p => model.Categories.Contains(p.Category))
.ToPagedList(currentPageIndex, DefaultPageSize);
model.AvailableCategories = allCategories;
return View("ProductsByCategories" , model);
}
public ActionResult IndexAjax ()
{
int currentPageIndex = 0 ;
IPagedList<Product> products = allProducts.ToPagedList(currentPageIndex, DefaultPageSize);
return View(products);
}
public ActionResult AjaxPage (int ? page)
{
ViewBag.Title = "Browse all products" ;
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
IPagedList<Product> products = allProducts.ToPagedList(currentPageIndex, DefaultPageSize);
return PartialView("_ProductGrid" , products);
}
public ActionResult Bootstrap (int ? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
return View(allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}
public ActionResult Bootstrap3 (int ? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0 ;
return View(allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}
}
Home文件夹里视图:
Index.cshtml
@{
ViewBag.Title = "ASP.NET MVC分页示例 - 首页";
}
@section featured {
<section class ="featured" >
<div class ="content-wrapper" >
<hgroup class ="title" >
<h2 > @ViewBag.Title</h2 >
</hgroup >
<p >
</p >
</div >
</section >
}
<dl >
<dt > @Html.ActionLink("简单的分页", "Index", "Paging")</dt >
<dd > 产品列表的分页示例</dd >
</dl >
<dl >
<dt > @Html.ActionLink("分页过滤 #1", "ViewByCategory", "Paging")</dt >
<dd > 按类别过滤的产品列表</dd >
</dl >
<dl >
<dt > @Html.ActionLink("分页过滤 #2", "ViewByCategories", "Paging")</dt >
<dd >
由多个类别过滤的产品列表<br />
此演示还使用强类型的viewmodel,它结合了结果和类别.
</dd >
</dl >
<dl >
<dt > @Html.ActionLink("一个区域的简单分页", "Index", "Paging", new {Area = "Area51"}, null)</dt >
<dd > 分页还支持区域</dd >
</dl >
<dl >
<dt > @Html.ActionLink("使用AJAX进行分页", "IndexAjax", "Paging")</dt >
<dd > 分页通过jquery支持unobtrusive AJAX。</dd >
</dl >
<dl >
<dt > @Html.ActionLink("可选择的分页显示模板", "Bootstrap", "Paging")</dt >
<dd > 分页结合Twitter Bootstrap</dd >
</dl >
<dl >
<dt > @Html.ActionLink("另一个可选的分页显示模板", "Bootstrap3", "Paging")</dt >
<dd >
分页与Bootstrap 3组合。此示例还仅显示页码,而不包含上一个和下一个链接。
</dd >
</dl >
<dl >
<dt > @Html.ActionLink("使用自定义页面路由值键的分页", "CustomPageRouteValueKey", "Paging")</dt >
<dd > 分页支持在生成分页链接时指定用于“page”的路由值键</dd >
</dl >
Paging文件夹里视图:
Bootstrap.cshtml
@using MvcPaging.Demo.Models
@model IPagedList<MvcPaging.Demo.Models.Product >
@{
Layout = null;
ViewBag.Title = "Twitter Bootstrap布局的分页";
}
<!DOCTYPE html>
<html lang ="en" >
<head >
<meta charset ="utf-8" >
<title > @ViewBag.Title</title >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<link href ="@Url.Content(" ~ /Content /Css /bootstrap.min.css ")" rel ="stylesheet" >
<style >
body {
padding-top : 60 px ;
}
</style >
<link href ="@Url.Content(" ~ /Content /SyntaxHighlighter /shCore.css ")" rel ="stylesheet" type ="text/css" />
<link href ="@Url.Content(" ~ /Content /SyntaxHighlighter /shThemeDefault.css ")" rel ="stylesheet" type ="text/css" />
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shCore.js ")"> </script >
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shBrushCSharp.js ")"> </script >
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shBrushXml.js ")"> </script >
</head >
<body >
<div class ="navbar navbar-fixed-top" >
<div class ="navbar-inner" >
<div class ="container" >
<a class ="btn btn-navbar" data-toggle ="collapse" data-target =".nav-collapse" >
<span class ="icon-bar" > </span > <span class ="icon-bar" > </span > <span class ="icon-bar" > </span >
</a > <a class ="brand" href ="#" > ASP.NET MVC Paging sample</a >
<div class ="nav-collapse" >
<ul class ="nav" >
<li > @Html.ActionLink("首页", "Index", "Home", new {area = String.Empty}, null)</li >
<li > @Html.ActionLink("About", "About", "Home", new {area = String.Empty}, null)</li >
</ul >
</div >
</div >
</div >
</div >
<div class ="container" >
<h1 > @ViewBag.Title</h1 >
<table class ="table table-striped" >
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (Product product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.DisplayTemplate("BootstrapPagination")
.MaxNrOfPages(14)
.AlwaysAddFirstPageNumber()
.SetPreviousPageText("←")
.SetNextPageText("→")
)
@{
var sourceModel = new ViewSourceViewModel();
sourceModel.RazorCode = @"
@using MvcPaging.Demo.Models
@model IPagedList<Product >
@{
Layout = null;
ViewBag.Title = ""Pager with Twitter Bootstrap layout"";
}
<!DOCTYPE html>
<html lang ="" en"" >
<head >
<meta charset ="" utf-8"" >
<title > @ViewBag.Title</title >
<meta name ="" viewport"" content ="" width=device-width, initial-scale =1.0"" >
<link href ="" @Url.Content(""~ /Content /Css /bootstrap.min.css "")"" rel ="" stylesheet"" >
<style >
body
{
padding-top : 60 px ;
}
</style >
</head >
<body >
<div class ="" navbar navbar-fixed-top "">
<div class ="" navbar-inner"" >
<div class ="" container"" >
<a class ="" btn btn-navbar "" data-toggle ="" collapse"" data-target ="" .nav-collapse"" > <span
class ="" icon-bar"" > </span > <span class ="" icon-bar"" > </span > <span class ="" icon-bar"" > </span >
</a > <a class ="" brand"" href ="" #"" > ASP.NET MVC Paging sample</a >
<div class ="" nav-collapse"" >
<ul class ="" nav"" >
<li > @Html.ActionLink(""首页"", ""Index"", ""Home"", new { area = String.Empty }, null)</li >
<li > @Html.ActionLink(""About"", ""About"", ""Home"", new { area = String.Empty }, null)</li >
</ul >
</div >
</div >
</div >
</div >
<div class ="" container"" >
<h1 > @ViewBag.Title</h1 >
<table class ="" table table-striped "">
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (var product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.DisplayTemplate(""BootstrapPagination"")
.MaxNrOfPages(14)
.AlwaysAddFirstPageNumber()
.SetPreviousPageText(""←"")
.SetNextPageText(""→"")
)
</div >
</body >
@model PaginationModel
<div class ="" pagination"" >
<ul >
@foreach (var link in Model.PaginationLinks)
{
@BuildLink(link)
}
</ul >
</div >
@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);
}
}
aBuilder.SetInnerText(link.DisplayText);
liBuilder.InnerHtml = aBuilder.ToString();
@Html.Raw(liBuilder.ToString())
}
";
sourceModel.ControllerCode = @"
public ActionResult Bootstrap(int? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
return View(this.allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}";
}
@Html.Partial("ViewSource", sourceModel)
</div >
</body >
</html >
Bootstrap3.cshtml
@using MvcPaging.Demo.Models
@model IPagedList<MvcPaging.Demo.Models.Product >
@{
Layout = null;
ViewBag.Title = "Twitter Bootstrap 3布局的分页";
}
<!DOCTYPE html>
<html lang ="en" >
<head >
<meta charset ="utf-8" >
<title > @ViewBag.Title</title >
<meta name ="viewport" content ="width=device-width, initial-scale=1.0" >
<link href ="@Url.Content(" ~ /Content /Css /bootstrap3.min.css ")" rel ="stylesheet" >
<style >
body {
padding-top : 60 px ;
}
</style >
<link href ="@Url.Content(" ~ /Content /SyntaxHighlighter /shCore.css ")" rel ="stylesheet" type ="text/css" />
<link href ="@Url.Content(" ~ /Content /SyntaxHighlighter /shThemeDefault.css ")" rel ="stylesheet" type ="text/css" />
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shCore.js ")"> </script >
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shBrushCSharp.js ")"> </script >
<script type ="text/javascript" src ="@Url.Content(" ~ /Scripts /SyntaxHighlighter /shBrushXml.js ")"> </script >
</head >
<body >
<a class ="sr-only" href ="#content" > Skip navigation</a >
<header class ="navbar navbar-inverse navbar-fixed-top bs-docs-nav" role ="banner" >
<div class ="container" >
<div class ="navbar-header" >
<button class ="navbar-toggle" type ="button" data-toggle ="collapse" data-target =".bs-navbar-collapse" >
<span class ="sr-only" > Toggle navigation</span >
<span class ="icon-bar" > </span >
<span class ="icon-bar" > </span >
<span class ="icon-bar" > </span >
</button >
</div >
<nav class ="collapse navbar-collapse bs-navbar-collapse" role ="navigation" >
<ul class ="nav navbar-nav" >
<li > @Html.ActionLink("首页", "Index", "Home", new {area = String.Empty}, null)</li >
<li > @Html.ActionLink("About", "About", "Home", new {area = String.Empty}, null)</li >
</ul >
</nav >
</div >
</header >
<div class ="container" >
<h1 > @ViewBag.Title</h1 >
<table class ="table table-striped" >
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (Product product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.DisplayTemplate("Bootstrap3Pagination")
.MaxNrOfPages(14)
.AlwaysAddFirstPageNumber()
.HidePreviousAndNextPage()
)
@{
var sourceModel = new ViewSourceViewModel();
sourceModel.RazorCode = @"
@using MvcPaging.Demo.Models
@model IPagedList<Product >
@{
Layout = null;
ViewBag.Title = ""Pager with Bootstrap 3 layout"";
}
<!DOCTYPE html>
<html lang ="" en"" >
<head >
<meta charset ="" utf-8"" >
<title > @ViewBag.Title</title >
<meta name ="" viewport"" content ="" width=device-width, initial-scale =1.0"" >
<link href ="" @Url.Content(""~ /Content /Css /bootstrap3.min.css "")"" rel ="" stylesheet"" >
<style >
body {
padding-top : 60 px ;
}
</style >
</head >
<body >
<a class ="" sr-only"" href ="" #content"" > Skip navigation</a >
<header class ="" navbar navbar-inverse navbar-fixed-top bs-docs-nav "" role ="" banner"" >
<div class ="" container"" >
<div class ="" navbar-header"" >
<button class ="" navbar-toggle"" type ="" button"" data-toggle ="" collapse"" data-target ="" .bs-navbar-collapse"" >
<span class ="" sr-only"" > Toggle navigation</span >
<span class ="" icon-bar"" > </span >
<span class ="" icon-bar"" > </span >
<span class ="" icon-bar"" > </span >
</button >
</div >
<nav class ="" collapse navbar-collapse bs-navbar-collapse "" role ="" navigation"" >
<ul class ="" nav navbar-nav "">
<li > @Html.ActionLink(""首页"", ""Index"", ""Home"", new { area = String.Empty }, null)</li >
<li > @Html.ActionLink(""About"", ""About"", ""Home"", new { area = String.Empty }, null)</li > s
</ul >
</nav >
</div >
</header >
<div class ="" container"" >
<h1 > @ViewBag.Title</h1 >
<table class ="" table table-striped "">
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (var product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.DisplayTemplate(""Bootstrap3Pagination"")
.MaxNrOfPages(14)
.AlwaysAddFirstPageNumber()
.HidePreviousAndNextPage()
)
</div >
</body >
@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())
}";
sourceModel.ControllerCode = @"
public ActionResult Bootstrap(int? page)
{
int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
return View(this.allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}";
}
@Html.Partial("ViewSource", sourceModel)
</div >
</body >
</html >
@using MvcPaging.Demo.Models
@model IPagedList<MvcPaging.Demo.Models.Product >
@{
ViewBag.Title = "浏览所有产品(自定义页面路由值键)";
}
<h2 > @ViewBag.Title</h2 >
<table class ="grid" >
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (Product product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
<div class ="pager" >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.PageRouteValueKey("Search.page")
.AlwaysAddFirstPageNumber())
</div >
@{
var sourceModel = new ViewSourceViewModel();
sourceModel.RazorCode = @"
@using MvcPaging.Demo.Models
@model IPagedList<Product >
@{
ViewBag.Title = ""Browse all products (custom page route value key)"";
}
<h2 > @ViewBag.Title</h2 >
<table class ="" grid"" >
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (var product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
<div class ="" pager"" >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount).Options(o => o
.PageRouteValueKey(""Search.page"")
.AlwaysAddFirstPageNumber())
</div >
";
sourceModel.ControllerCode = @"
public ActionResult CustomPageRouteValueKey(SearchModel search)
{
int currentPageIndex = search.page.HasValue ? search.page.Value - 1 : 0;
return View(this.allProducts.ToPagedList(currentPageIndex, DefaultPageSize));
}
";
}
@Html.Partial("ViewSource", sourceModel)
Index.cshtml
@using MvcPaging.Demo.Models
@model IPagedList<MvcPaging.Demo.Models.Product >
@{
ViewBag.Title = "浏览所有产品";
}
<h2 > @ViewBag.Title</h2 >
<table class ="grid" >
<thead >
<tr >
<th > Product name</th >
<th > Category</th >
</tr >
</thead >
<tbody >
@foreach (Product product in Model)
{
<tr >
<td > @product.Name</td >
<td > @product.Category</td >
</tr >
}
</tbody >
</table >
<div class ="pager" >
@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount)
</div >
IndexAjax.cshtml
@using MvcPaging.Demo .Models
@model IPagedList<MvcPaging.Demo .Models .Product >
@{
ViewBag.Title = "浏览所有产品(ajax)"
}
<h2>@ViewBag.Title </h2>
<div id="gridcontainer" >
@Html.Partial ("_ProductGrid" , Model)
</div>
ProductsByCategories.cshtml
@using MvcPaging.Demo .Models
@model MvcPaging.Demo .Models .ViewByCategoriesViewModel
@{
ViewBag.Title = "按多选类别浏览产品"
}
<h2>@ViewBag.Title </h2>
@using (Html.BeginForm ("ViewByCategories" , "Paging" , FormMethod.Get ))
{
<p>
Select category or categories:
<ul>
@foreach (string category in Model.AvailableCategories )
{
<li>
<label>
<input type="checkbox" name="categories" value="@category" @if (Model.Categories .Any (c => c == category))
{
<text> checked="checked" </text>
} />
@category
</label>
</li>
}
</ul>
<input type="submit" value="Browse" />
</p>
}
@if (Model.Products .Any ())
{
<table class="grid" >
<thead>
<tr>
<th>Product name</th>
<th>Category</th>
</tr>
</thead>
<tbody>
@foreach (Product product in Model.Products )
{
<tr>
<td>@product.Name </td>
<td>@product.Category </td>
</tr>
}
</tbody>
</table>
<div class="pager" >
@Html.Pager (Model.Products .PageSize , Model.Products .PageNumber , Model.Products .TotalItemCount ).Options (o => o
.AddRouteValueFor (m => m.Categories )
.DisplayFirstAndLastPage ()
.SetFirstPageText ("First" )
.SetLastPageText ("Last" )
.SetPreviousPageText ("Prev" )
.SetNextPageText ("Next" ))
Displaying @Model.Products .ItemStart - @Model.Products .ItemEnd of @Model.Products .TotalItemCount item(s)
</div>
}
ProductsByCategory.cshtml
@using MvcPaging.Demo .Models
@model IPagedList<MvcPaging.Demo .Models .Product >
@{
ViewBag.Title = "按类别浏览产品"
}
<h2>@ViewBag.Title </h2>
@using (Html.BeginForm ("ViewByCategory" , "Paging" , FormMethod.Get ))
{
<p>
Select a category:
@Html.DropDownList ("categoryName" )
<input type="submit" value="Browse" />
</p>
}
@if (Model.Count () > 0 )
{
<table class="grid" >
<thead>
<tr>
<th>Product name</th>
<th>Category</th>
</tr>
</thead>
<tbody>
@foreach (Product product in Model)
{
<tr>
<td>@product.Name </td>
<td>@product.Category </td>
</tr>
}
</tbody>
</table>
<div class="pager" >
@Html.Pager (Model.PageSize , Model.PageNumber , Model.TotalItemCount ).Options (o => o.AddRouteValue ("categoryname" , ViewBag.CategoryDisplayName ))
Displaying @Model.ItemStart - @Model.ItemEnd of @Model.TotalItemCount item(s)
</div>
}
视图文件结构:
运行结果如图: