Tag-хелпер пагинации с сортировкой и фильтрацией

Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7

Последнее обновление: 09.12.2019

В прошлой теме было рассмотрено создание ссылок для постраничного перехода. Теперь посмотрим, как мы можем заменить эти ссылки на специальный tag-хелпер для постраничной навигации.

Добавим в проект новый класс PageLinkTagHelper:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using FilterSortPagingApp.Models;
using System.Collections.Generic;

namespace FilterSortPagingApp.TagHelpers
{
    public class PageLinkTagHelper : TagHelper
    {
        private IUrlHelperFactory urlHelperFactory;
        public PageLinkTagHelper(IUrlHelperFactory helperFactory)
        {
            urlHelperFactory = helperFactory;
        }
        [ViewContext]
        [HtmlAttributeNotBound]
        public ViewContext ViewContext { get; set; }
        public PageViewModel PageModel { get; set; }
        public string PageAction { get; set; }

        [HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]
        public Dictionary<string, object> PageUrlValues { get; set; } = new Dictionary<string, object>();

        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            IUrlHelper urlHelper = urlHelperFactory.GetUrlHelper(ViewContext);
            output.TagName = "div";

            // набор ссылок будет представлять список ul
            TagBuilder tag = new TagBuilder("ul");
            tag.AddCssClass("pagination");

            // формируем три ссылки - на текущую, предыдущую и следующую
            TagBuilder currentItem = CreateTag(PageModel.PageNumber, urlHelper);

            // создаем ссылку на предыдущую страницу, если она есть
            if (PageModel.HasPreviousPage)
            {
                TagBuilder prevItem = CreateTag(PageModel.PageNumber - 1, urlHelper);
                tag.InnerHtml.AppendHtml(prevItem);
            }

            tag.InnerHtml.AppendHtml(currentItem);
            // создаем ссылку на следующую страницу, если она есть
            if (PageModel.HasNextPage)
            {
                TagBuilder nextItem = CreateTag(PageModel.PageNumber + 1, urlHelper);
                tag.InnerHtml.AppendHtml(nextItem);
            }
            output.Content.AppendHtml(tag);
        }

        TagBuilder CreateTag(int pageNumber, IUrlHelper urlHelper)
        {
            TagBuilder item = new TagBuilder("li");
            TagBuilder link = new TagBuilder("a");
            if (pageNumber == this.PageModel.PageNumber)
            {
                item.AddCssClass("active");
            }
            else
            {
                PageUrlValues["page"] = pageNumber;
                link.Attributes["href"] = urlHelper.Action(PageAction, PageUrlValues);
            }
			item.AddCssClass("page-item");
            link.AddCssClass("page-link");
            link.InnerHtml.Append(pageNumber.ToString());
            item.InnerHtml.AppendHtml(link);
            return item;
        }
    }
}

Ранее уже было рассмотрено создание tag-хелпера для постраничной навигации, и в данном случае основная часть повторяется. Единственным исключением является свойство PageUrlValues:

[HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]
public Dictionary<string, object> PageUrlValues { get; set; } = new Dictionary<string, object>();

Это свойство представляет словарь Dictionary<string, object>, в котором каждой строке будет сопоставлен некоторый объект.

Его отличительной чертой является атрибут [HtmlAttributeName(DictionaryAttributePrefix = "page-url-")]. Он указывает, что при применении хелпера в представлении мы сможем передать ему некоторые значения через атрибуты с префиксом "page-url-". Например:

<page-link page-url-action="Index" page-url-number="2"></page-link>

В этом случае в словаре PageUrlValues окажутся две пары значений: {"action" : "Index"} и {"number" : 2}. То есть ключи в словаре будут представлять названия атрибутов без префикса page-url-, а их значения - значения в этих атрибутах. Таким образом, мы можем передать в словарь PageUrlValues произвольное количество значений.

Далее все эти значения мы можем использовать, к примеру, для создания навигационных ссылок:

PageUrlValues["page"] = pageNumber;
link.Attributes["href"] = urlHelper.Action(PageAction, PageUrlValues);

Применим этот хелпер в представлении:

@using FilterSortPagingApp.Models
@model IndexViewModel
@addTagHelper *, FilterSortPagingApp
@{
    ViewData["Title"] = "Home Page";
}
<h1>Список пользователей</h1>
<form method="get">
    <div class="form-group form-inline">
        <label>Имя: </label>
        <input name="name" value="@Model.FilterViewModel.SelectedName" class = "form-control" />

        <label>Компания: </label>
        <select name="company" asp-items="Model.FilterViewModel.Companies" class="form-control"></select>

        <input type="submit" value="Фильтр" class="btn btn-outline-dark" />
    </div>
</form>

<table class="table">
    <tr>
        <th>
            <a asp-action="Index"
               asp-route-sortOrder="@(Model.SortViewModel.NameSort)"
               asp-route-name="@(Model.FilterViewModel.SelectedName)"
               asp-route-company="@(Model.FilterViewModel.SelectedCompany)">Имя</a>
        </th>
        <th>
            <a asp-action="Index" asp-route-sortOrder="@(Model.SortViewModel.AgeSort)"
               asp-route-name="@(Model.FilterViewModel.SelectedName)"
               asp-route-company="@(Model.FilterViewModel.SelectedCompany)">Возраст</a>
        </th>
        <th>
            <a asp-action="Index" asp-route-sortOrder="@(Model.SortViewModel.CompanySort)"
               asp-route-name="@(Model.FilterViewModel.SelectedName)"
               asp-route-company="@(Model.FilterViewModel.SelectedCompany)">Компания</a>
        </th>
    </tr>
    @foreach (User u in Model.Users)
    {
        <tr><td>@u.Name</td><td>@u.Age</td><td>@u.Company.Name</td></tr>
    }
</table>

<page-link page-model="Model.PageViewModel" page-action="Index"
           page-url-name="@(Model.FilterViewModel.SelectedName)"
           page-url-company="@(Model.FilterViewModel.SelectedCompany)"
           page-url-sortorder="@(Model.SortViewModel.Current)"></page-link>
Tag-хелпер для постраничной навигации с сортировкой и фильтрацией в ASP.NET Core MVC
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850