14 июня 2012 г.

Делаем простой постраничный вывод данных (paged list) для ASP.NET Mvc

Думаю, что даже не стоит начинать рассказ о том, что такое постраничный вывод данных из БД, и зачем это нужно. Довольно стандартная и распространенная вещь для большинства сайтов. Единственное, в чем остается определиться, так это вариант реализации этого самого PagedList-а. Конечно же, многие (каюсь, я тоже) иногда начинают изобретать свои механизмы пейджинга. При этом забывают о том, что готовых решений уже полным полно, в том числе и для ASP.NET Mvc.
Сегодня мы создадим простейший постраничный вывод данных в виде таблицы из БД. Для реализации задуманного будем использовать NuGet-пакет PagedList.Mvc. Выбор пал на него, именно из за простоты понимания и внедрения.

Итак, начнем.
Сначала нужно добавитьв наш проект, через NuGet, пакет PagedList.Mvc. Он же включает в себя и пакет PagedList:

После установки пакета, у нас появятся ссылки на сборки:

А так же файл стилей, для организации красивой панели навигации по страницам:

Этого нам будет достаточно для задуманного.
Будем делать вывод данных на главной странице проекта, поэтому давайте напишем экшн, для получения данных из БД, и их передачи в представление:
   1:  public ActionResult Index(int? page)
   2:  {
   3:      ViewBag.Message = "Welcome to ASP.NET MVC!";
   4:   
   5:      NorthwindEntities _db = new NorthwindEntities();
   6:   
   7:      var model = _db.Products.ToList();
   8:   
   9:      int pageNumber = page ?? 1;
  10:      int pageSize = 10;
  11:   
  12:      return View(model.ToPagedList(pageNumber, pageSize));
  13:  }

Мы добавили входящий параметр "page", который будет обозначать текущею страницу набора данных. Далее получаем из БД список товаров, и передаем их в представление. Здесь важная вещь - приведение списка продуктов к типу IPagedList т.к. именно с ним работает установленный пакет. Еще, при приведении списка "toPagedList", мы задаем номер страницы (он приходит в экшн, а по-умолчанию равен 1) и кол-во записей, отображаемых на одной странице. Ах да, не забудьте подключить в контроллер пространство имен PagedList (using PagedList;). С контроллером закончили.

Теперь перейдем к представлению, ведь это самое главное для нас. Модель представления - список IPagedList. Также в представление подключен файл стилей PagedList.css:
   1:  @model PagedList.IPagedList<_MvcApplication.Models.Product>
   2:  @using PagedList.Mvc
   3:  @{
   4:      ViewBag.Title = "Index";
   5:  }
   6:  <link href="@Url.Content("/Content/PagedList.css")" rel="stylesheet"
          type="text/css" />
   7:  <h2>
   8:      Products</h2>
   9:  <table width="100%">
  10:      <tr>
  11:          <th>
  12:              ProductName
  13:          </th>
  14:          <th>
  15:              QuantityPerUnit
  16:          </th>
  17:          <th>
  18:              UnitPrice
  19:          </th>
  20:          <th>
  21:              UnitsInStock
  22:          </th>
  23:          <th>
  24:              UnitsOnOrder
  25:          </th>
  26:          <th>
  27:              ReorderLevel
  28:          </th>
  29:      </tr>
  30:      @foreach (var item in Model)
  31:      {
  32:          <tr>
  33:              <td>
  34:                  @Html.DisplayFor(modelItem => item.ProductName)
  35:              </td>
  36:              <td>
  37:                  @Html.DisplayFor(modelItem => item.QuantityPerUnit)
  38:              </td>
  39:              <td>
  40:                  @Html.DisplayFor(modelItem => item.UnitPrice)
  41:              </td>
  42:              <td>
  43:                  @Html.DisplayFor(modelItem => item.UnitsInStock)
  44:              </td>
  45:              <td>
  46:                  @Html.DisplayFor(modelItem => item.UnitsOnOrder)
  47:              </td>
  48:              <td>
  49:                  @Html.DisplayFor(modelItem => item.ReorderLevel)
  50:              </td>
  51:          </tr>
  52:      }
  53:  </table>
  54:  <div style="text-align: center;">
  55:      @Html.PagedListPager(Model, page => Url.Action("Index", new { page }), 
  56:          new PagedListRenderOptions { LinkToFirstPageFormat = "<<", 
  57:              LinkToPreviousPageFormat = "Назад",
  58:              LinkToNextPageFormat = "Вперед",
  59:              LinkToLastPageFormat = ">>" })
  60:  </div>

Самое главное здесь - панель навигации, реализуемая хэлпером PagedListPager. Чтобы использовать его, необходимо подключить на страницу  пространство имен "PagedList.Mvc".
Хотя этот хелпер и имеет множество настроек и параметров, он все-же очень прост в использовании. Сначала мы указываем для него модель (наш IPagedList-список), потом указываем экшн, к которому нужно обращаться за следующей/предыдущей порцией данных, плюс параметр-номер страницы. Ну а дальше идут чисто визуальные настройки панели навигации. Там и переименовывать ссылки можно, и включать\отключать их видимость, и еще много чего полезного. Советую покопаться самим.

Ну вот мы и сделали все, что хотели.
Вот, что у нас получилось в итоге:

Для правильной работы пейджинга больше ничего не нужно. Вся его логика скрыта от нас в установленном пакете, но нам она не так уж и важна. Главное, что все работает, и при этом нам не пришлось придумывать что-то свое.

_____
Исходники