21

我正在尝试根据类别过滤器和 ItemsPerPage 显示经过过滤的产品列表,但是在尝试将其与 PagedList 一起使用时遇到了一些问题。

如果我需要编写自己的分页代码,或者有没有办法使用 PagedList 获得所需的结果,具有 PagedList 专业知识的人可以建议我。

我正在使用 LINQ 的 Skip & Take 函数来仅获取需要在当前页面上显示的行数,但我仍然希望分页链接根据过滤器的总数显示页面。

例如:我的搜索过滤器找到 50 个结果,但由于我每页的行数是 10 项,我使用 LINQ 的 Skip() 和 Take() 只返回 10 行。我仍然需要在我的 View.cshtml 中显示页面链接<< 1 | 2 | 3 | 4 | 5 >> 现在使用默认的 PagedList,我只得到<< 1 >>,我知道为什么我只看到一个页面,但只是想知道如何让它显示正确数量的页面链接,同时只获得一个子集结果。

**我的目标是将优化的查询写入数据库,以便网页响应性能更快。

这是我的 Action Method 代码的样子。代码得到了正确的结果,但分页没有按照我的需要工作:

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));
}

这是视图中处理分页的代码片段。我查看了项目的 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>
4

5 回答 5

26

我遇到了完全相同的问题,最终我使用了 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>
于 2014-01-23T10:03:23.153 回答
3

ToPagedList在内部使用TakeandSkip当您使用IQueryable<T>类的扩展时,这将导致您需要的数据库查询。它还将 检索TotalItemCount到其元数据中。

有时您可能需要将查询结果带入内存,因为您使用的方法无法翻译成 sql。这意味着您必须将PagedListback 转换为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 类的新实例,该类包含已划分的子集以及有关超集大小和子集在其中位置的信息。

于 2015-03-02T15:04:36.053 回答
2

如果使用 PagedList 的方法,则不需要同时使用 LINQ.skip().take(). 如果这样做,那么您将预先限制列表,并且使用该库将毫无意义,因为您首先过滤列表以获取pagesize结果.skip().take()然后将这些pagesize结果再次过滤到pagesize,这当然会一样,但是 PagedList 不知道总数是多少。

如果您想确保不加载所有结果,只需发送一个IQueryableto PagedList 而不是Enumerableor List。PagedList 将为您添加.Skip().Take(),您的数据库将只返回这些结果。

于 2014-01-14T01:20:57.810 回答
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);
于 2013-11-13T00:12:00.190 回答
1

上面的解释是正确的。但是当您分配静态选择列表时..

new StaticPagedList<Product>(products, page, PageSize, 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

或 new StaticPagedList(products, page, PageSize, count*pagesize);

因此它提供了页面中的所有可用计数。

于 2014-06-17T08:31:05.407 回答