Создание пагинации

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

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

Одной из распространенных задач при работе с данными является проблема пагинации или разделения данных на несколько блоков - страниц, которые выводятсяв представление по отдельности и которые сопровождаются удобной навигацией по страницам. Для создания пагинации мы можем воспользоваться готовыми плагинами. Но в данном случае мы сами создадим механизм для постраничного вывода.

Вначале опрелелим модель, данные которой будем выводить:

public class Phone
{
    public int Id { get; set; }
    public string Model { get;set;}
    public string Producer { get; set; }
}

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

public class PageInfo
{
    public int PageNumber { get; set; } // номер текущей страницы
    public int PageSize { get; set; } // кол-во объектов на странице
    public int TotalItems { get; set; } // всего объектов
    public int TotalPages  // всего страниц
    {
        get { return (int)Math.Ceiling((decimal)TotalItems / PageSize); }
    }
}
public class IndexViewModel
{
    public IEnumerable<Phone> Phones { get; set; }
    public PageInfo PageInfo { get; set; }
}

Так как вместе с данными моделей телефонов потребуется также использовать в представлении модель пагинации, то они инкапсулируются классом IndexViewModel.

Теперь определим контроллер и его метод для вывода данных:

public class HomeController : Controller
{
    List<Phone> phones;
    public HomeController()
    {
        phones = new List<Phone>();
        phones.Add(new Phone { Id = 1, Model = "Samsung Galaxy III", Producer = "Samsung" });
        phones.Add(new Phone { Id = 2, Model = "Samsung Ace II", Producer = "Samsung" });
        phones.Add(new Phone { Id = 3, Model = "HTC Hero", Producer = "HTC" });
        phones.Add(new Phone { Id = 4, Model = "HTC One S", Producer = "HTC" });
        phones.Add(new Phone { Id = 5, Model = "HTC One X", Producer = "HTC" });
        phones.Add(new Phone { Id = 6, Model = "LG Optimus 3D", Producer = "LG" });
        phones.Add(new Phone { Id = 7, Model = "Nokia N9", Producer = "Nokia" });
        phones.Add(new Phone { Id = 8, Model = "Samsung Galaxy Nexus", Producer = "Samsung" });
        phones.Add(new Phone { Id = 9, Model = "Sony Xperia X10", Producer = "SONY" });
        phones.Add(new Phone { Id = 10, Model = "Samsung Galaxy II", Producer = "Samsung" });
    }
    public ActionResult Index(int page=1)
    {
        int pageSize = 3; // количество объектов на страницу
        IEnumerable<Phone> phonesPerPages=phones.Skip((page - 1) * pageSize).Take(pageSize);
        PageInfo pageInfo = new PageInfo { PageNumber=page, PageSize=pageSize, TotalItems=phones.Count};
        IndexViewModel ivm = new IndexViewModel { PageInfo = pageInfo, Phones = phonesPerPages };
        return View(ivm);
    }
}

Для простоты примера я создаю обычный список в конструкторе контроллера, однако это мог бы быть и вывод из базы данных.

Метод Index в качестве параметра принимает номер страницы. По умолчанию номер страницы будет равняться единице.

В самом методе с помощью комбинации методов Skip и Take происходит отбор нужной части данных: метод Skip() пропускает определенное количество данных, которое передается в параметре, а метод Take() извлекает определенное количество.

Для создания механизма пагинации в представлении удобно использовать хелперы. Создадим собственный хелпер. Для этого добавим в проект папку Helpers и затем добавим в нее следующий класс:

using System.Text;
using System.Web;
using System.Web.Mvc;
//.............................
public static class PagingHelpers
{
    public static MvcHtmlString PageLinks(this HtmlHelper html,
        PageInfo pageInfo, Func<int, string> pageUrl)
    {
        StringBuilder result = new StringBuilder();
        for (int i = 1; i <= pageInfo.TotalPages; i++)
        {
            TagBuilder tag = new TagBuilder("a");
            tag.MergeAttribute("href", pageUrl(i));
            tag.InnerHtml = i.ToString();
			// если текущая страница, то выделяем ее,
			// например, добавляя класс
            if (i == pageInfo.PageNumber)
            {
                tag.AddCssClass("selected");
                tag.AddCssClass("btn-primary");
            }
            tag.AddCssClass("btn btn-default");
            result.Append(tag.ToString());
        }
        return MvcHtmlString.Create(result.ToString());
    }
}

Данный хелпер просто создет блок ссылок, а также добавляет им классы для визуализации. Классы могут быть любыми, но в данном случае использовались стандартные классы bootstrap.

И теперь определим представление, которое использовать пагинацию:

@model ManualPaginApp.Models.IndexViewModel
@using ManualPaginApp.Helpers
@{
    ViewBag.Title = "Home Page";
}
<table class="table">
    <tr>
        <td>Модель</td>
        <td>Производитель</td>
    </tr>
    @foreach (var item in Model.Phones)
    {
        <tr>
            <td>@item.Model</td>
            <td>@item.Producer</td>
        </tr>
    }
</table>
<br />
<div class="btn-group">
    @Html.PageLinks(Model.PageInfo, x => Url.Action("Index",new { page = x}))
</div>

Поскольку хелпер пагинации находится в папке Helpers, то необходимо вначале представления подключить данное пространство имен using ManualPaginApp.Helpers. И хелпер пагинации Html.PageLinks сделают всю работу по формированию блока ссылок в сответствии с заложенной в нем логикой..

В итоге получим примерно следующую картину:

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850