如何在asp.net核心剃须刀页面中实现分页

时间:2018-06-19 12:49:13

标签: c# razor asp.net-core

我正在用ef学习asp.net核心剃须刀页面。我想用我的桌子实现分页,我已经检查了本教程

https://docs.microsoft.com/en-us/aspnet/core/data/ef-rp/sort-filter-page?view=aspnetcore-2.1

但是它仅支持前后,我已经研究了很长时间,所有解决方案都与asp.net核心mvc有关,但是我使用的是剃刀页面,我的项目中没有控制器,任何想法实施?

这就是我想要实现的效果

enter image description here

 <form method="get" asp-page="./Index">
                <nav aria-label="Page navigation">
                    <ul class="pagination">
                        <li>
                            <a href="#" aria-label="Previous">
                                <span aria-hidden="true">&laquo;</span>
                            </a>
                        </li>
                        @{
                            var totalPages = Model.Products.Count % 2 == 0 ? Model.Products.Count / 2 : Model.Products.Count / 2 + 1;
                        }
                        @for (int i = 1; i <= totalPages; i++)
                        {
                            <li><a asp-page="./Index" asp-route-id="@i">@i</a></li>
                        }
                        <li>
                            <a href="#" aria-label="Next">
                                <span aria-hidden="true">&raquo;</span>
                            </a>
                        </li>
                    </ul>
                </nav>
            </form>

cshtml.cs

  public async Task OnGetAsync(string sortOrder, string searchString, string shopString, string statusString, int page)
        {}

4 个答案:

答案 0 :(得分:13)

分页相对简单。有可用的库可以帮您完成,但是我开始发现它们比它们值得的麻烦更多。

您需要从请求中获取三条信息(或设置为默认值):

  1. 页码(默认为1)
  2. 页面大小(通常默认为10,但可以根据需要设置)
  3. 排序(并非绝对必要,但是您至少应按某种顺序排序,以使结果在页面之间保持一致)

页码和页面大小为您提供“跳过”和“获取”值:

var skip = (page - 1) * size;
var take = size;

然后您可以通过以下方式获取结果:

var pageOfResults = await query.Skip(skip).Take(take).ToListAsync();

queryIQueryable的地方-直接使用您的DbSet或应用DbSet子句的WhereOrderBy

然后,您只需要统计项目总数即可计算页面:

var count = await query.CountAsync();

专业提示,您可以通过以下操作并行化两个查询(结果和总数):

var resultsTask = query.Skip(skip).Take(take).ToListAsync();
var countTask = query.CountAsync();

var results = await resultsTask;
var count = await countTask;

任务热返回或已启动。 await关键字仅保留其余代码的延续,直到任务完成。结果,如果您等待每一行,它们将按顺序完成,但是如果您先启动这两行,然后再等待每一行,则它们将并行处理。

无论如何,一旦您有了计数:

var totalPages = (int)Math.Ceil(Decimal.Divide(count, size));
var firstPage = 1;
var lastPage = totalPages;
var prevPage = Math.Max(page - 1, firstPage);
var nextPage = Math.Min(page + 1, lastPage);

注意:您可以根据分别等于firstPage还是lastPage来确定是否显示第一个/上一个和最后一个/下一个按钮。

然后,使用此信息构建您自己的模型,然后可以将其发送到视图以呈现结果并生成分页HTML。

答案 1 :(得分:1)

您可以使用JW.Pager NuGet软件包(https://www.nuget.org/packages/JW.Pager/

这是一个示例剃须刀页面模型,可分页显示150个项目:

using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.RazorPages;
using JW;

namespace RazorPagesPagination.Pages
{
    public class IndexModel : PageModel
    {
        public IEnumerable<string> Items { get; set; }
        public Pager Pager { get; set; }

        public void OnGet(int p = 1)
        {
            // generate list of sample items to be paged
            var dummyItems = Enumerable.Range(1, 150).Select(x => "Item " + x);

            // get pagination info for the current page
            Pager = new Pager(dummyItems.Count(), p);

            // assign the current page of items to the Items property
            Items = dummyItems.Skip((Pager.CurrentPage - 1) * Pager.PageSize).Take(Pager.PageSize);
        }
    }
}

这是剃刀页面页面,其中包含分页列表和分页器控件的html:

@page
@model RazorPagesPagination.Pages.IndexModel

<!-- items being paged -->
<table class="table table-sm table-striped table-bordered">
    @foreach (var item in Model.Items)
    {
        <tr>
            <td>@item</td>
        </tr>
    }
</table>                

<!-- pager -->
@if (Model.Pager.Pages.Any())
{
    <nav class="table-responsive">
        <ul class="pagination justify-content-center d-flex flex-wrap">
            @if (Model.Pager.CurrentPage > 1)
            {
                <li class="page-item">
                    <a class="page-link" href="/">First</a>
                </li>
                <li class="page-item">
                    <a class="page-link" href="/?p=@(Model.Pager.CurrentPage - 1)">Previous</a>
                </li>
            }

            @foreach (var p in Model.Pager.Pages)
            {
                <li class="page-item @(p == Model.Pager.CurrentPage ? "active" : "")">
                    <a class="page-link" href="/?p=@p">@p</a>
                </li>
            }

            @if (Model.Pager.CurrentPage < Model.Pager.TotalPages)
            {
                <li class="page-item">
                    <a class="page-link" href="/?p=@(Model.Pager.CurrentPage + 1)">Next</a>
                </li>
                <li class="page-item">
                    <a class="page-link" href="/?p=@(Model.Pager.TotalPages)">Last</a>
                </li>
            }
        </ul>
    </nav>
}

有关更多详细信息,我在http://jasonwatmore.com/post/2018/10/15/aspnet-core-razor-pages-pagination-example

上发布了带有示例项目的完整教程。

答案 2 :(得分:0)

我为.net Core Razor Pages创建了一个分页taghelper,可以在html标签或appsettings.json中对其进行配置,以显示/隐藏上一个,下一个,倒数第二个按钮,最大显示页面数以及更多自定义设置。可用

该项目可作为nuget包(和github)安装:

Install-Package LazZiya.TagHelpers -Version 1.0.2

在此处查看安装步骤: http://ziyad.info/en/articles/21-Paging_TagHelper_for_ASP_NET_Core

实时演示和所有设置: http://demo.ziyad.info/en/paging

使用appsettings.json进行分页配置将有助于获得更清晰的html代码,并且可以更改应用程序中所有或特定分页taghelper的分页设置。

答案 3 :(得分:0)

我做了这个实现,将有关该主题的一些答案混合在一起,希望对您有所帮助。

添加一个PagedResultBase类(您可以扩展添加所需的其他属性):

public abstract class PagedResultBase
{
    public int CurrentPage { get; set; }
    public int PageCount { get; set; }
    public int PageSize { get; set; }
    public int RowCount { get; set; }
}

添加一个PagedResult类:

public class PagedResult<T> : PagedResultBase where T : class
{
    public ICollection<T> Results { get; set; }

    public PagedResult()
    {
        Results = new List<T>();
    }
}

添加扩展名为IQueryableExtensions的{​​{1}}:

GetPagedResult

您已完成:

public static class IQueryableExtensions
{
    public async static Task<PagedResult<T>> GetPagedResultAsync<T>(this IQueryable<T> query, int currentPage, int pageSize) where T : class
    {
        var skip = (currentPage - 1) * pageSize;
        var take = pageSize;

        var rowCount = await query.CountAsync();
        var results = await query.Skip(skip).Take(take).ToListAsync();

        var pagedResult = new PagedResult<T> {
            CurrentPage = currentPage,
            PageCount = (int)Math.Ceiling(decimal.Divide(rowCount, pageSize)),
            PageSize = pageSize,
            RowCount = rowCount,
            Results = results
        };

        return pagedResult;
    }
}