Элемент управления ListView
189ASP.NET --- Основы ASP.NET --- Элемент управления ListView
ListView — это исключительно гибкий привязанный к данным элемент управления, отображающий свое содержимое на основе определяемых вами шаблонов. В отличие от Repeater, элемент ListView добавляет высокоуровневые средства, такие как возможность выбора и редактирования, которые работают точно так же, как аналогичные средства GridView. Но в отличие от GridView, элемент ListView не поддерживает модели, основанной на полях, для создания быстрых и простых таблиц с минимальным кодом разметки.
С разных точек зрения ListView можно трактовать либо как более гибкую версию GridView, требующую больше работы, либо как более насыщенную средствами версию простого элемента Repeater, который появился в ASP.NET 1.x.
ListView включает более широкий набор шаблонов, чем GridView. Эти шаблоны перечислены в таблице ниже:
Режим | Описание |
---|---|
ItemTemplate | Устанавливает содержимое каждого элемента данных (если вы не используете AlternatingItemTemplate) или каждой нечетной ячейки (если используете) |
AlternatingItemTemplate | Применяется в сочетании с ItemTemplate для различного форматирования четных и нечетных строк |
ItemSeparatorTemplate | Устанавливает содержимое разделителя, размещаемого между элементами |
SelectedItemTemplate | Устанавливает содержимое элемента, выбранного в данный момент. Можно использовать то же содержимое, что и ItemSeparatorTemplate, но с другим форматированием, или же выбрать отображение расширенного вида с дополнительными деталями для выбранного элемента |
EditItemTemplate | Устанавливает элементы управления, используемые для элемента в режиме редактирования |
InsertItemTemplate | Устанавливает элементы управления, используемые для вставки нового элемента |
LayoutTemplate | Устанавливает разметку, обертывающую ваш список элементов |
GroupTemplate | Устанавливает разметку, обертывающую каждую группу элементов, если используется средство группирования |
GroupSeparatorTemplate | Устанавливает содержимое разделителя групп элементов |
EmptyItemTemplate | Устанавливает содержимое, используемое для заполнения пустых значений в последней группе, если применяется группирование. Например, если создаются группы из 5 элементов, а источником данных является коллекция из 13 объектов, то в последней группе будет не хватать 2 элементов |
EmptyDataTemplate | Устанавливает разметку, используемую в случае пустого привязанного объекта данных (т.е. не содержащего записей или объектов) |
Наиболее частая причина использования ListView связана с необходимостью создания необычной компоновки, например, чтобы построить таблицу, размещающую более одного элемента в одной строке, или же вообще не использующую обычную табличную компоновку. При построении страницы, предназначенной для отображения больших объемов данных, разработчики на ASP.NET обычно сначала обращаются к GridView, a ListView применяют в более специализированных сценариях.
При отображении некоторых данных в ListView вы следуете тому же процессу, что и в случае элемента GridView, состоящего из столбцов TemplateField. Сначала вы создаете разметку для шаблонов, которые хотите использовать. Как минимум, понадобится шаблон ItemTemplate, который представляет содержимое для каждого элемента. Ниже приведен пример:
<asp:ListView ID="listEmployees" runat="server" DataSourceID="getEmployeesSDS">
<ItemTemplate>
<span>
<b>
<%# Eval("EmployeeID") %> -
<%# Eval("TitleOfCourtesy") %> <%# Eval("FirstName") %>
<%# Eval("LastName") %>
</b>
<hr />
<small><i>
<%# Eval("Address") %><br />
<%# Eval("City") %>, <%# Eval("Country") %>,
<%# Eval("PostalCode") %><br />
<%# Eval("HomePhone") %></i>
<br />
<br />
<%# Eval("Notes") %>
</small><hr /><br />
</span>
</ItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="getEmployeesSDS" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT * FROM Employees" />
При визуализации элемент управления ListView осуществляет проход по привязанным данным и отображает ItemTemplate для каждого элемента. Все это содержимое размещается внутри обычного элемента <span>:
Часто возникает желание определить шаблон LayoutTemplate для получения большего контроля над расположением элементов. В этом случае список элементов размещается внутри LayoutTemplate. Поведение по умолчанию элемента ListView без LayoutTemplate эквивалентно использованию примерно следующего шаблона LayoutTemplate:
<asp:ListView ID="listEmployees" runat="server" DataSourceID="getEmployeesSDS">
<ItemTemplate>
...
</ItemTemplate>
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server"></asp:PlaceHolder>
</LayoutTemplate>
</asp:ListView>
При создании LayoutTemplate для ListView потребуется указать, куда должно быть вставлено содержимое ItemTemplate. Это делается добавлением заполнителя - элемент, который будет дублироваться по одному для каждого элемента привязанных данных. Чтобы обозначить элемент как заполнитель, необходимо просто установить его ID в itemPlaceHolder, как показано выше в примере.
Заполнитель должен быть серверным элементом управления — другими словами, ему нужен атрибут runat="server". В этом примере используется удобный веб-элемент управления PlaceHolder, но вместо него можно указать серверный элемент <span> или <div>.
Именно шаблон LayoutTemplate придает такую гибкость элементу ListView. Другие элементы управления данными используют шаблоны для содержимого, но не для всей структуры. С помощью LayoutTemplate можете легко адаптировать этот пример для использования таблицы. Например, если вы хотите поместить каждый элемент в отдельную строку (как это делает GridView), для заполнителя элемента необходимо использовать строку таблицы (элемент <tr>):
<LayoutTemplate>
<table border="1">
<tr id="itemPlaceHolder" runat="server" />
</LayoutTemplate>
Теперь каждый элемент может начинать новую строку (с помощью <tr>) и добавлять ячейки по мере необходимости (посредством <td>):
<ItemTemplate>
<tr>
<td>...</td>
...
</tr>
</ItemTemplate>
По сравнению с GridView, элемент Listview обладает одним концептуальным недостатком — у него есть только один шаблон для отображения элементов. Чтобы понять, чем это может ограничивать, рассмотрим, что случится, если вы захотите создать многостолбцовое отображение с использованием Listview. Вам нужно будет добавить заголовки столбцов над Listview, а затем определить содержимое всех столбцов в ItemTemplate. Это отлично работает, но приводит к серьезным неудобствам, когда требуется внести кажущиеся тривиальными изменения — вроде изменения последовательности столбцов.
Ради интереса можете создать табличную компоновку, которая была бы невозможной для обычного элемента GridView — такую, которая размещает каждый элемент в отдельном столбце. Концептуально это не сложно. Нужно просто использовать ячейку таблицы (элемент <td>) в качестве заполнителя:
<LayoutTemplate>
<table border="1">
<tr id="groupPlaceholder" runat="server"
style="vertical-align:top; border:1px solid black">
<td id="itemPlaceHolder" runat="server" />
</tr>
</table>
</LayoutTemplate>
Теперь шаблон LayoutTemplate должен начинаться с дескриптора <td>:
<ItemTemplate>
<td>
<b>
<%# Eval("EmployeeID") %>-
<%# Eval("TitleOfCourtesy") %> <%# Eval("FirstName") %> <%# Eval("LastName") %></b><hr />
<small><i>
<%# Eval("Address") %><br />
<%# Eval("City") %>, <%# Eval("Country") %>,
<%# Eval("PostalCode") %><br />
<%# Eval("HomePhone") %></i><br />
<br />
<%# Eval("Notes") %><br />
<br />
</small>
</td>
</ItemTemplate>
Результат быстро станет трудночитаемым, если отображаемый набор данных окажется достаточно объемным (если не применять разбиение на страницы):
Группирование
Элемент Listview предоставляет возможность создать несколько более структурированные отображения, которые решают проблему, показанную на рисунке выше. Трюк заключается в применении группирования, которое позволяет указать дополнительный уровень компоновки, используемой для размещения небольших групп записей внутри общей компоновки.
Чтобы воспользоваться группированием, начать следует с установки свойства GroupItemCount, определяющего количество элементов данных в каждой группе:
<asp:ListView ID="listEmployees" GroupItemCount="3" ...>
К сожалению, средство группирования ListView не работает в связке с информацией из привязанных данных. Например, в случае привязки коллекции объектов Product не существует способа разделить их по группам на основе ценовых диапазонов или категорий товаров. Вместо этого группы ListView всегда имеют фиксированный размер. Максимум, что можно — это сделать размер групп настраиваемым пользователем (скажем, применив дополнительный элемент управления, подобный раскрывающемуся списку, из которого пользователь сможет выбирать число для применения в GroupItemCount).
После установки размера группы понадобится изменить LayoutTemplate. Это связано с тем, что общая компоновка более не содержит элементов данных. Вместо этого она содержит группы, которые, в свою очередь, содержат элементы. Чтобы отразить этот факт, вы должны изменить ID с itemPlaceholder на groupPlaceholder. В данном примере каждая группа представляет собой отдельную строку:
<LayoutTemplate>
<table border="1">
<tr id="groupPlaceholder" runat="server"></tr>
</table>
</LayoutTemplate>
Далее необходимо применить шаблон GroupTemplate, который используется в качестве оболочки для каждой группы. GroupTemplate должен предоставлять заполнитель элемента, который находился ранее в LayoutTemplate. В этом примере каждый элемент является отдельной ячейкой:
<GroupTemplate>
<tr>
<td runat="server" id="itemPlaceholder" />
</tr>
</GroupTemplate>
Теперь ItemTemplate может начинаться с дескриптора <td>, так что каждый элемент — это ячейка внутри строки. В свою очередь, каждая строка — это группа из трех элементов данных в общей таблице. На рисунке ниже показан результат:
При использовании группирования последняя группа может быть заполнена не полностью. Например, в предыдущем примере создается группа из трех элементов. Если количество элементов данных не кратно трем, последняя группа будет неполной. Во многих случаях это не представляет проблемы, но в некоторых возникает сложность — например, если нужно сохранить некоторую структуру или поместить какое-то альтернативное содержимое в таблицу. В такой ситуации можно предоставить новое содержимое, используя EmptyItemTemplate.
Разбиение на страницы
В отличие от других элементов управления, рассматриваемых ранее, ListView не имеет жестко связанного средства разбиения на страницы. Взамен ListView поддерживает другой элемент управления, предназначенный для разбиения на страницы, а именно: DataPager.
Идея, положенная в основу DataPager, заключается в том, что он предлагает простой, согласованный способ использования разбиения на страницы для широкого разнообразия элементов управления. В настоящее время ListView — единственный элемент, поддерживающий DataPager. Однако вполне резонно ожидать, что в будущих версиях DataPager будет работать с другими элементами управления ASP.NET.
Одно из преимуществ DataPager заключается в том, что вам предоставляется гибкость в произвольном размещении его внутри общей компоновки — просто за счет размещения дескриптора в правильном месте LayoutTemplate. Рассмотрим пример совершенно типичного размещения DataPager в нижней части ListView, с кнопками для перемещения вперед и назад на одну страницу либо для быстрого перехода на первую или последнюю страницы:
<LayoutTemplate>
<table border="1">
<tr id="groupPlaceholder" runat="server"></tr>
</table>
<asp:DataPager runat="server" ID="ContactsDataPager" PageSize="3">
<Fields>
<asp:NextPreviousPagerField ShowFirstPageButton="true" ShowLastPageButton="true"
FirstPageText="|<< " LastPageText=" >>|"
NextPageText=" > " PreviousPageText=" < " />
</Fields>
</asp:DataPager>
</LayoutTemplate>
DataPager также усекает привязанные данные, так что ListView получает соответствующее подмножество этих данных. В текущем примере страницы ограничены тремя элементами. На рисунке показаны кнопки перемещения по страницам: