我正在尝试根据Category过滤器和ItemsPerPage显示已过滤的产品列表,但在尝试将其与PagedList一起使用时,我遇到了一些问题。
如果我需要编写自己的分页代码,或者有办法使用PagedList获得我需要的结果,那么具有PagedList专业知识的人可以建议我。
我正在使用LINQ的Skip&使用函数只获取当前页面上需要显示的行数,但我仍然希望根据过滤器的总数来分页链接显示页面。
例如:我的搜索过滤器找到50个结果,但由于我的每页行数是10项,我使用LINQ的Skip()& Take()只返回10行。我仍然需要在我的View.cshtml中显示页面链接<< 1 | 2 | 3 | 4 | 5>> 现在使用默认的PagedList,我只得到<< 1>> ,我知道为什么我只看到一个页面,但我只想知道如何使其显示正确数量的页面链接,同时只获得一部分结果。
**我的目标是为数据库编写优化查询,以便网页响应速度快。
以下是我的Action方法代码。代码获得了正确的结果,但分页不起作用,因为我需要它:
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
return View(products.ToList().ToPagedList(page, PageSize));
}
以下是View中处理分页的代码段。我查看了项目的Github网站,但找不到提供自定义页面的扩展方法。我认为它只会根据“每页的项目数”和@Model中产品的Count()来呈现页数:
@model IPagedList<Product>
//foreach loop that renders the @Model
//Code that displays the pagination using PagedList
<div style="text-align:center">
@Html.PagedListPager(Model, page => Url.Action("List", new { page = page, category = ViewBag.CurrentCategory }), PagedListRenderOptions.OnlyShowFivePagesAtATime
)
</div>
答案 0 :(得分:24)
我遇到了完全相同的问题,最后我使用了StaticPagedList。你可以做这样的事情
public ViewResult List(int page =1, string category =null)
{
if (category != null) this.CurrentCategory = category;
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
var count = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory).Count();
var resultAsPagedList = new StaticPagedList<Product>(products, page, PageSize, count);
return View(resultAsPagedList);
}
对于视图,您只需要替换模型类型
@model StaticPagedList<Product>
答案 1 :(得分:3)
ToPagedList
在内部使用Take
和Skip
,当您使用IQueryable<T>
类的扩展名时,这将导致您需要的数据库查询。它还会将TotalItemCount
检索到其元数据中。
有时您可能需要将查询结果带入内存,因为您使用的方法无法转换为sql。这意味着您必须将PagedList
转换回Enumerable
。您可以使用StaticPagedList
方法解决此问题,如下所示:
var superset= repository.Products
.Where(p => this.CurrentCategory == null
|| p.Category == this.CurrentCategory)
.OrderBy(p => p.ProductID)
.ToPagedList(page, PageSize);
var subset = superset
.AsEnumerable()
.Select(p => new ProductViewModel
{
OtherData = p.UntranslateableMethod()
})
var model = new StaticPagedList<ProductViewModel>(subset,
superset.GetMetaData());
}
从评论中的方法摘要:
初始化PagedList.StaticPagedList类的新实例 包含已经划分的子集和有关的信息 超集的大小和子集在其中的位置。
答案 2 :(得分:2)
你仍然可能需要单独索要一个计数。
var products = repository.Products
.Where(p => this.CurrentCategory == null || p.Category == this.CurrentCategory);
var numProds = products.Count();
var mypage = products.OrderBy(p => p.ProductID)
.Skip((page -1) * PageSize)
.Take(PageSize);
答案 3 :(得分:2)
如果使用PagedList的方法,则无需使用LINQ .skip()
和.take()
。如果你这样做,那么你是预先限制列表,使用库是没有意义的,因为你首先过滤列表以pagesize
和.skip()
获得.take()
结果然后将那些pagesize
结果再次过滤到pagesize
,这当然会是相同的,但是然后PagedList不知道总数是多少。
如果您想确保未加载所有结果,只需将IQueryable
发送到PagedList,而不是Enumerable
或List
。 PagedList会为您添加.Skip()
和.Take()
,您的数据库只会返回这些结果。
答案 4 :(得分:0)
以上解释是正确的。 但是当您分配静态选择列表时..
new StaticPagedList<Product>(products, page, PageSize, count);.
显示实际计数的页面链接数量较少。 如果Count为10,如果您的页面大小为5,则仅显示2页。
如果要显示所有页面链接可用数量, 然后
pass count*5 ie count*pagesize
new StaticPagedList<Product>(products, page, PageSize, count*5);//in my case page size is 5
或新的StaticPagedList(产品,页面,PageSize,count * pagesize);
因此它提供了所有可用的页数。