以下是使用Bootstrap分页的解决方案。
在 ProductController.cs 中:
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace TestControllers
{
public class ProductController : Controller
{
private readonly ILogger<ProductController> _logger;
public ProductController(ILogger<ProductController> logger)
{
_logger = logger;
}
public IActionResult Products()
{
//Generate test products data
var products = Enumerable.Range(1,1000).Select(i=>
new Product(){Id=i,BrandId=i%10+1, CategoryId=i%20 + 1, ExpirationDate="12/"+(i%31 + 1) + "/2020", Name="Product"+i, OriginCity="City"+(i%40 + 1), OriginCountry="Country"+(i%50 + 1), ProducerName="Producer"+ i+100 + 1, ProductionDate="1/"+(i%31 + 1) + "/2020"}
).ToList();
return View(products);
}
}
public class Product
{
public int Id { get; set; }
public int CategoryId { get; set; }
public int BrandId { get; set; }
public string Name { get; set; }
public string ProducerName { get; set; }
public string OriginCity { get; set; }
public string OriginCountry { get; set; }
public string ProductionDate { get; set; }
public string ExpirationDate { get; set; }
}
}
在 Product.cshtml 中:
@model List<TestControllers.Product>
@using System.Linq;
@{
ViewData["Title"] = "Products Page";
var category = this.Context.Request.Query["category"];
var page = this.Context.Request.Query["page"];
var categoryInt = !string.IsNullOrEmpty(category) ? int.Parse(category) : 1;
var pageInt = !string.IsNullOrEmpty(page) ? int.Parse(page) : 1;
var productsPerPage = 10;
//Get pager contents
Func<string,string, int, int,int, Func<int,Dictionary<string,string>>, string> getPager = (controller,action,pages, currentPage,numberOfPages, getParameters) =>
{
//Get query string for a given page number
Func<int, string> getQueryString = (page1) =>
{
var queryString = getParameters(page1).ToList().Aggregate("", (content, next) =>
{
content = !string.IsNullOrEmpty(content) ? content + "&" : content;
content += string.Format("{0}={1}", next.Key, next.Value);
return content;
});
queryString = !string.IsNullOrEmpty(queryString) ? "?" + queryString : queryString;
return queryString;
};
var pager = "<nav aria-label=\"...\"><ul class=\"pagination .pagination-lg\">";
if(currentPage>1)
{
pager+= "<li class=\"page-item\"><a class=\"page-link\" href=\"" + string.Concat("/", controller, "/", action, getQueryString(currentPage-1)) + "\">Previous</a></li>";
}
else
{
pager += "<li class=\"page-item disabled\"><span class=\"page-link\">Previous</span></li>";
}
var renderedPageSets = new List<List<int>>();
var renderedPages = 0;
if(pages<= numberOfPages)
{
renderedPageSets.Add(Enumerable.Range(1, pages).ToList());
}
else
{
while (renderedPages < pages)
{
var lastSetPage = renderedPages + numberOfPages;
if (lastSetPage <= pages)
{
renderedPageSets.Add(Enumerable.Range(++renderedPages, numberOfPages).ToList());
}
else
{
renderedPageSets.Add(Enumerable.Range(pages - numberOfPages + 1, numberOfPages).ToList());
}
if(renderedPageSets.Last().Contains(currentPage))
{
break;
}
renderedPages = lastSetPage;
}
}
var renderedPageSet = renderedPageSets.First(s => s.Contains(currentPage));
if(renderedPageSet.First()!=1)
{
pager += "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>";
}
pager = renderedPageSet.Aggregate(pager, (currentPagerContent, nextPage) => {
currentPagerContent += "<li class=\"page-item"+(currentPage==nextPage? " active":"") + " \"><a class=\"page-link\" href=\""+string.Concat("/",controller,"/",action, getQueryString(nextPage)) + "\">"+nextPage+"</a></li>";
return currentPagerContent;
});
if (renderedPageSet.Last() != pages)
{
pager += "<li class=\"page-item disabled\"><span class=\"page-link\">...</span></li>";
}
if (currentPage < pages)
{
pager += "<li class=\"page-item\"><a class=\"page-link\" href=\"" + string.Concat("/", controller, "/", action, getQueryString(currentPage + 1)) + "\">Next</a></li>";
}
else
{
pager += "<li class=\"page-item disabled\"><span class=\"page-link\">Next</span></li>";
}
pager += "</li></ul></nav>";
return pager;
};
}
<div class="text-center">
<h1 class="display-4">Products</h1>
</div>
<div class="card" style="">
<div class="card-header">
<div>
@{
var categories = Model.Select(i => i.CategoryId).Distinct().Count();
}
<h2>Categories:</h2> @Html.Raw(getPager("Product", "Products", categories, categoryInt, 10, (category1) => { return new Dictionary<string, string>() { { "page", "1" }, { "category", category1.ToString() } }; }))
</div>
<h3>Products in category @categoryInt</h3>
</div>
<br />
<a asp-action="Add" asp-controller="Product" class="btn btn-success btn-sm" style="width:148px">Add a New Product</a>
<table class="table table-bordered">
<tr>
<th>Category</th>
<th>Name</th>
<th>Producer Name</th>
<th>Origin City</th>
<th>Origin Country</th>
<th>Production Date</th>
<th>Expiration Date</th>
<th> </th>
</tr>
@foreach (var product in Model.Where(i => i.CategoryId == categoryInt).Skip((pageInt - 1) * productsPerPage).Take(productsPerPage))
{
<tr>
<td>@product.CategoryId</td>
<td>@product.Name</td>
<td>@product.ProducerName</td>
<td>@product.OriginCity</td>
<td>@product.OriginCountry</td>
<td>@product.ProductionDate</td>
<td>@product.ExpirationDate</td>
<td>
<a asp-action="Edit" asp-controller="Product" asp-route-id="@product.Id" class="btn btn-warning btn-sm">Edit</a>
<a asp-action="Delete" asp-controller="Product" asp-route-id="@product.Id" class="btn btn-danger btn-sm">Delete</a>
</td>
</tr>
}
</table>
<div>
@{
var categoryProductsPages = (int)Math.Ceiling(((double)Model.Where(i => i.CategoryId == categoryInt).Count()) / productsPerPage);
}
@Html.Raw(getPager("Product", "Products", categoryProductsPages, pageInt, 10, (page1) => { return new Dictionary<string, string>() { { "page", page1.ToString() }, { "category", category } }; }))
</div>
</div>
结果视图: