Help us understand the problem. What is going on with this article?

ASP.NET Core MVCでページング機能を実装する

ページング機能の実装方法を探していたら、一からコードを書いて実装する方法と、パッケージを利用して実装する方法があったので紹介します。

環境

  • ASP.NET Core2.2
  • ASP.NET Core MVC
  • Bootstrap4
  • Visual Studio 2019
  • X.PagedList.Mvc.Core7.9.0(NuGetパッケージ)

店舗管理機能で、登録店舗の一覧ページにページング機能を実装することを想定しています。

1からコードを書いて実装する

参考サイト

Students/Index にページングを追加する(Microsoft)

1.ページング用のクラスを新規作成

PaginatedList.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity
{
    public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            TotalPages = (int)Math.Ceiling(count / (double)pageSize);

            this.AddRange(items);
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 1);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex < TotalPages);
            }
        }

        public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
        {
            var count = await source.CountAsync();
            var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
            return new PaginatedList<T>(items, count, pageIndex, pageSize);
        }
    }
}

2.Indexアクションメソッドを変更

Controllers/ShopController.cs
        public async Task<IActionResult> Index(int? pageNumber)
        {
            // 「編集」「詳細」ページから戻ってくる際のページ番号保持
            ViewData["pageNumber"] = pageNumber ?? 1;

            // ソートデータ取得用のクエリ発行
            var shops = _context.Shop.Select(m => m);

            // 1ページ内の項目レコード表示数
            int pageSize = 5;

            return View(await PaginatedList<Shop>.CreateAsync(shops.AsNoTracking(), pageNumber ?? 1, pageSize));
        }

3.ページングリンクの追加

先頭のmodelステートメントでPaginatedList< T >を使用する

View/Shop/Index.cshtml
    @model PaginatedList<Models.Shop>

    ----------------------
        一覧表示処理(tableとか)
    ----------------------



//ページャーを表示したい箇所に下記を挿入
    @{
        var prevDisabled = !Model.HasPreviousPage ? "disabled" : "";
        var nextDisabled = !Model.HasNextPage ? "disabled" : "";
        var active = "";
    } 

    <nav aria-label="">
        <ul class="pagination">
            <li class="page-item @prevDisabled">
                <a asp-action="Index"  asp-route-pageNumber="@(Model.PageNumber - 1)" class="page-link">Previous</a>
            </li>
            @for (int i = 1; i < Model.TotalPages + 1; i++)
            {
                active = Model.PageNumber == i ? "active" : "";
                <li class="page-item @active">
                    <a asp-action="Index"  asp-route-pageNumber="@i" class="page-link ">@i</a>
                </li>
            }
            <li class="page-item @nextDisabled">
                <a asp-action="Index"  asp-route-pageNumber="@(Model.PageNumber + 1)" class="page-link">Next</a>
            </li>
        </ul>
    </nav>

表示内容

pager1.PNG

X.PagedList.Mvc.Coreパッケージを利用する

参考サイト

X.PagedList

1.パッケージの追加

追加方法は割愛。画像は下記のやつ。
キャプチャ.PNG
バージョンは7.9.0

2.Indexアクションメソッドを変更

Controllers/ShopController.cs
        public async Task<IActionResult> Index(int? page)
        {
            var pageNumber = page ?? 1;
            IQueryable<Shop> query = _context.Shop;
            return View(query.ToPagedList(pageNumber, 3));
        }

3.ページングリンクの追加

先頭のmodelステートメントでPaginatedList< T >を使用する

View/Shop/Index.cshtml
@using X.PagedList.Mvc.Core;
@using X.PagedList;

    ----------------------
        一覧表示処理(tableとか)
    ----------------------

//ページャーを表示したい箇所に下記を挿入
@Html.PagedListPager(
    (IPagedList)Model,
    page => Url.Action("Index", new { page }),
    new X.PagedList.Mvc.Common.PagedListRenderOptionsBase    //Bootstrap4を利用する場合はオプションを利用してタグにクラスを追加しないとデザインが反映されない
    {
        LiElementClasses = new string[] { "page-item" },
        PageClasses = new string[] { "page-link" },
        MaximumPageNumbersToDisplay = 5,                                                 //表示するページャーの数
        DisplayLinkToNextPage = X.PagedList.Mvc.Common.PagedListDisplayMode.Never,       //「次へ」の非表示設定
        DisplayLinkToPreviousPage = X.PagedList.Mvc.Common.PagedListDisplayMode.Never,   //「前へ」の非表示設定
        DisplayLinkToFirstPage = X.PagedList.Mvc.Common.PagedListDisplayMode.Never,      //「最初へ」の非表示設定
        DisplayLinkToLastPage = X.PagedList.Mvc.Common.PagedListDisplayMode.Never,       //「最後へ」の表示設定
    }
)

表示内容

pager2.PNG

オプションに関して

参考サイトのGitHubの「README.md」に記載してある。

使ってみて

大体「X.PagedList.Mvc.Core」使っておけばOKな気がする。
表示方法のオプションとか、独自でタグにクラスもつけれるので、困ることはあんまりないかなと。(Bootstrap3とBootstrap4でタグのクラスのつけ方が違うので、そこだけ注意。)
ただ、Microsoftのドキュメント読むのも面白いし勉強になるので、MVC勉強中の人はドキュメント読むのもお勧めします。

参考サイト

X.PagedList
Students/Index にページングを追加する(Miscrosoft)
ページ送り(Pagination)

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away