Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Одной из распространенных задач при работе с данными является проблема пагинации или разделения данных на несколько блоков - страниц, которые выводятсяв представление по отдельности и которые сопровождаются удобной навигацией по страницам. Для создания пагинации мы можем воспользоваться готовыми плагинами. Но в данном случае мы сами создадим механизм для постраничного вывода.
Вначале опрелелим модель, данные которой будем выводить:
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
сделают всю работу по формированию блока ссылок в сответствии с заложенной в нем логикой..
В итоге получим примерно следующую картину: