Советы и приемы при работе с ListView - DataPager и ListView

ОГЛАВЛЕНИЕ

DataPager и ListView

Элемент управления ListView предоставляет средства разбиения на страницы через новый элемент управления DataPager. Элемент управления DataPager – это элемент управления разбиением на страницы общего назначения, который может быть использован любым привязанным к данным элементом управления, реализующим интерфейс IPageableItemContainer. В ASP.NET 3.5 ListView является единственным таким элементом.

Элемент управления DataPager может отображать встроенный или основанный на шаблоне интерфейс пользователя. Каждый раз, когда пользователь выполняет переход на новую страницу, элемент управления DataPager вызывает метод на интерфейсе IPageableItemContainer. От этого метода ожидается установка внутренних переменных в разбитом на страницы элементе управления, так что лишь определенная страница данных отображается в ходе следующей операции их привязки.

Оказывается, что выбор правильной страницы данных остается проблемой привязанного к данным элемента управления – в данном случае это ListView. Как и другие элементы управления «представления» в ASP.NET, элемент управления ListView полагается на внешний код при разбиении на страницы. Если данные корректно привязываются через источник данных, то код пользователя должен позаботиться о разбитых на страницы данных. В ином случае, если данные привязаны через элемент управления источника данных, следует правильно настроить этот элемент для поддержки разбиения на страницы.

Элементы управления LinqDataSource и ObjectDataSource предлагают встроенные возможности разбиения на страницы. У LinqDataSource имеется свойство AutoPage для включения или отключения разбиения на страницы по умолчанию. Для иерархических данных необходимо также убедиться, что у контекста данных LINQ установлены верные параметры загрузки. Интерфейс программирования LinqDataSource не имеет свойств для установки свойства LoadOptions для объекта контекста данных. Однако, обрабатывая событие ContextCreated, можно получить доступ к только что созданному контексту данных и настроить его по вкусу:

void LinqDataSource1_ContextCreated(
  object sender, LinqDataSourceStatusEventArgs e)
{
  // Get a reference to the data context
  DataContext db = e.Result as DataContext;

  if (db != null)
  {
  DataLoadOptions opt = new DataLoadOptions();
  opt.LoadWith<Customer>(c => c.Orders);
  opt.LoadWith<Order>(o => o.Employee);
  opt.LoadWith<Order>(o => o.Order_Details);
  db.LoadOptions = opt;
  }
}

В качестве альтернативы этому действию можно использовать объект ObjectDataSource для предоставления данных и реализации логики разбиения на страницы. Далее, в бизнес-объекте для доступа к данным можно использовать либо LINQ-SQL, либо простой ADO.NET.

Стоит, однако, упомянуть о трудности, с которой я столкнулся, когда использовал DataPager и ListView вместе. Первоначально у меня была страница содержимого с ListView и DataPager, размещенными в одном заполнителе для содержимого. Я установил ссылку на ListView в DataPager, используя свойство ControlID, как показано ниже. Все сработало отлично:

<asp:DataPager ID="DataPager1" runat="server" 
  PagedControlID="ListView1"
  PageSize="5" 
  EnableViewState="false">
  <Fields>
  <asp:NextPreviousPagerField 
  ShowFirstPageButton="true" 
  ShowLastPageButton="true" />
  </Fields>
</asp:DataPager>

Далее, я переместил DataPager в другую область содержимого на той же основной странице. И внезапно DataPager утратил способность сообщаться с элементом управления ListView. Проблема здесь находится в алгоритме, используемом DataPager для обнаружения разбитого на страницы элемента управления. Этот алгоритм не работает, если два элемента управления размещены в разных контейнерах именования. Чтобы обойти эту проблему, необходимо определить разбитый на страницы элемент управления, используя его полный, уникальный идентификатор (включающий сведения о контейнере именования). Увы, установить эти сведения декларативно не так-то просто.

Использовать блоки кода в стиле ASP нельзя, поскольку они воспринимаются как литералы, когда используются для установки свойства элемента управления сервера. Нельзя использовать и выражение привязки данных <%# ... %>, поскольку выражение вычисляется слишком поздно для нужд DataPager. Событие Load («Загрузка») происходит слишком поздно и заставит DataPager выдать исключение. Простейшим решением является программная установка свойства PagedControlID в событии Init страницы, вот так:

protected void Page_Init(object sender, EventArgs e)
{
  DataPager1.PagedControlID = ListView1.UniqueID;
}