简体   繁体   English

如何在asp.net core razor页面中实现分页

[英]How to implement pagination in asp.net core razor pages

I'm learning asp.net core razor pages with ef.我正在使用 ef 学习 asp.net 核心剃刀页面。 I want to implement pagination with my table, I have check this tutorial我想用我的表实现分页,我已经检查了这个教程

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

but it only support pre and next, I have researched for a long time, all of the solution are related to asp.net core mvc, but I'm using razor pages, there's no controller in my project, any ideas to implement?但它只支持pre和next,我研究了很长时间,所有解决方案都与asp.net core mvc有关,但我使用的是razor pages,我的项目中没有控制器,有什么想法可以实现吗?

This is the effect what I want to implement这是我想要实现的效果

在此处输入图片说明

 <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 cshtml.cs

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

Pagination is relatively simple.分页比较简单。 There's libraries available to do it for you, but I've started to find them more trouble than they're worth.有一些库可以为你做这件事,但我开始发现它们比它们的价值更麻烦。

You need three pieces of information from the request (or set to default values):您需要来自请求的三条信息(或设置为默认值):

  1. Page number (default to 1)页码(默认为 1)
  2. Page size (typically defaults to 10, but whatever you want)页面大小(通常默认为 10,但无论您想要什么)
  3. Sort (not strictly necessary, but you should at least order by something to keep the results consistent across pages)排序(并非绝对必要,但您至少应该按某种顺序进行排序,以保持页面之间的结果一致)

The page number and size give you your "skip" and "take" values:页码和大小为您提供“跳过”和“获取”值:

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

You can then fetch the results via:然后您可以通过以下方式获取结果:

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

Where query is an IQueryable - either your DbSet directly or the DbSet with a Where clause, OrderBy , etc. applied.其中query是一个IQueryable - 直接使用DbSet或应用了Where子句、 OrderBy等的DbSet

Then, you just need to the total number of items to figure the pages:然后,您只需要通过项目总数来计算页面:

var count = await query.CountAsync();

Pro Tip , you can parallelize the two queries (results and total count) by doing:专业提示,您可以通过执行以下操作并行化两个查询(结果和总计数):

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

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

Tasks return hot, or already started.任务返回热,或已经开始。 The await keyword simply holds the continuation of the rest of the code until the task completes. await关键字只是保持其余代码的继续,直到任务完成。 As a result, if you await each line, they'll complete in serial, but if you start both, first, and then await each, they'll process in parallel.因此,如果您等待每一行,它们将串行完成,但如果您先启动两条线,然后等待每条线,它们将并行处理。

Anyways, once you have the count:无论如何,一旦你有了计数:

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

Note: you can determine whether to show first/previous and last/next buttons based on whether they equal firstPage or lastPage , respectively.注意:您可以根据是否分别等于firstPagelastPage来确定是否显示第一个/上一个和最后一个/下一个按钮。

Then, just build yourself a model with this information, and you can send that to the view to render the results and generate the paging HTML.然后,只需使用此信息为自己构建一个模型,您就可以将其发送到视图以呈现结果并生成分页 HTML。

I have created a paging taghelper for .net Core Razor Pages, it can be configured within html tags or appsettings.json to show/ hide prev-next, first-last buttons, number of max displayed pages and more customization settings are available,我为 .net Core Razor 页面创建了一个分页标签助手,它可以在 html 标签或 appsettings.json 中配置以显示/隐藏上一个下一个、第一个最后一个按钮、最大显示页面数和更多自定义设置可用,

Install the nuget package:安装 nuget 包:

Install-Package LazZiya.TagHelpers

Add the taghelper to _ViewImports.cshtml将 taghelper 添加到 _ViewImports.cshtml

@addTagHelper *, LazZiya.TagHelpers

Finally add the paging control to the view:最后在视图中添加分页控件:

<paging 
    total-records="Model.TotalRecords" 
    page-no="Model.PageNo"
    query-string-value="@(Request.QueryString.Value)">
</paging>

[Update] [更新]

Starting from v3.1.0 query-string-value is not necessary to be passed, additonally all options is turned on by default.从 v3.1.0 开始不需要传递query-string-value ,另外所有选项默认开启。

<paging 
    total-records="Model.TotalRecords" 
    page-no="Model.PageNo">
</paging>

分页标签助手

Using appsettings.json for paging configurations will help to have more clean html code and it gives the ability to change paging settings on all or some paging taghelpers by once in the application.使用 appsettings.json 进行分页配置将有助于获得更干净的 html 代码,并且可以在应用程序中一次性更改所有或某些分页标签助手的分页设置。

See live demo for all settings: http://demo.ziyad.info/en/paging查看所有设置的现场演示: http : //demo.ziyad.info/en/paging

Related article: http://ziyad.info/en/articles/21-Paging_TagHelper_for_ASP_NET_Core相关文章:http: //ziyad.info/en/articles/21-Paging_TagHelper_for_ASP_NET_Core

You can use the JW.Pager NuGet package ( https://www.nuget.org/packages/JW.Pager/ )您可以使用JW.Pager NuGet 包 ( https://www.nuget.org/packages/JW.Pager/ )

Here's an example razor pages page model that paginates a list of 150 items:这是一个示例 razor pages 页面模型,它对 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);
        }
    }
}

And here's the razor pages page containing the html for the paged list and pager controls:这是包含分页列表和寻呼机控件的 html 的 razor 页面:

@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>
}

For more details I posted a full tutorial with example project at http://jasonwatmore.com/post/2018/10/15/aspnet-core-razor-pages-pagination-example有关更多详细信息,我在http://jasonwatmore.com/post/2018/10/15/aspnet-core-razor-pages-pagination-example 上发布了包含示例项目的完整教程

I made this implementation mixing together a few answers on the subject, I hope it helps someone.我将这个实现混合了一些关于这个主题的答案,我希望它对某人有所帮助。

Add a PagedResultBase class (that you can extend adding other properties you need):添加一个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; }
}

Add a PagedResult class:添加一个PagedResult类:

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

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

Add a IQueryableExtensions with a GetPagedResult extension:添加带有GetPagedResult扩展的IQueryableExtensions

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

You are done:你完成了:

var pagedResult = await MyContext.Posts.Where(p => p.Featured == true).GetPagedResultAsync(1, 10);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM