Отчет "Основной/подробности" с использованием маркированного списка основных записей с элементом управления DataList для подробных сведений (C#)
В этом руководстве мы сжимаем двухстраничный главный или подробный отчет предыдущего руководства на одну страницу, где отображается маркированный список имен категорий слева от экрана и продукты выбранной категории справа от экрана.
Введение
В предыдущем руководстве мы рассмотрели, как разделить главный или подробный отчет на двух страницах. На главной странице мы использовали элемент управления Repeater для отрисовки маркированного списка категорий. Каждое имя категории было гиперссылкой, которая при щелчке позволит пользователю перейти на страницу сведений, где двухколонок DataList показал эти продукты, принадлежащие выбранной категории.
В этом руководстве мы сжать двухстраничные учебники на одну страницу, где отображается маркированный список имен категорий в левой части экрана с каждым именем категории, отображаемым как LinkButton. Щелкнув одно из имен категории LinkButtons, вызывает обратную передачу и привязывает продукты выбранной категории к двум столбцам DataList справа от экрана. Помимо отображения имени каждой категории, повторитель слева показывает, сколько продуктов имеется для данной категории (см. рис. 1).
Рис. 1. Имя категории и общее количество продуктов отображаются слева (щелкните, чтобы просмотреть изображение полного размера)
Шаг 1. Отображение повтора в левой части экрана
Для этого руководства нам нужно иметь маркированный список категорий слева от выбранных продуктов категории. Содержимое на веб-странице можно разместить с помощью стандартных тегов абзаца HTML-элементов, неразрывных пробелов, <table>
s и т. д. или с помощью каскадных методов таблицы стилей (CSS). Все наши учебники до сих пор использовали методы CSS для позиционирования. Когда мы создали пользовательский интерфейс навигации на главной странице в руководстве по эталонным страницам и навигации сайта, мы использовали абсолютное расположение, указывая точное смещение пикселей для списка навигации и основного содержимого. Кроме того, CSS можно использовать для размещения одного элемента справа или слева от другого с плавающей запятой. Список маркированных категорий может отображаться слева от продуктов выбранной категории, плавая слева от объекта DataList.
CategoriesAndProducts.aspx
Откройте страницу из DataListRepeaterFiltering
папки и добавьте на страницу повторитель и dataList. Задайте для повторяющегося файла значение ID
Categories
и значение DataList CategoryProducts
. Перейдите в представление "Источник" и поместите элементы управления Repeater и DataList в собственные <div>
элементы. То есть заключите повторитель в <div>
элемент сначала, а затем DataList в свой собственный <div>
элемент непосредственно после повторяющегося элемента. Разметка на этом этапе должна выглядеть примерно так:
<div>
<asp:Repeater ID="Categories" runat="server">
</asp:Repeater>
</div>
<div>
<asp:DataList ID="CategoryProducts" runat="server">
</asp:DataList>
</div>
Чтобы с плавать повторяющимся элементом слева от DataList, необходимо использовать float
атрибут стиля CSS, как показано ниже.
<div>
Repeater
</div>
<div>
DataList
</div>
С float: left;
плавающей запятой <div>
первый элемент слева от второго. padding-right
Параметры width
указывают первые <div>
и width
сколько заполнений добавляется между <div>
содержимым элемента и его правым полем. Дополнительные сведения о плавающих элементах в CSS см . в разделе Floatutorial.
Вместо указания параметра стиля непосредственно с помощью атрибута style
первого <p>
элемента давайте создадим новый класс CSS с Styles.css
именемFloatLeft
:
.FloatLeft
{
float: left;
width: 33%;
padding-right: 10px;
}
Затем можно заменить <div>
<div class="FloatLeft">
на .
После добавления класса CSS и настройки разметки на CategoriesAndProducts.aspx
странице перейдите в конструктор. Вы должны увидеть повторитель, плавающий слева от DataList (хотя прямо сейчас оба отображаются как серые поля, так как мы еще не настроили свои источники данных или шаблоны).
Рис. 2. Повторитель плавает слева от списка данных (щелкните, чтобы просмотреть изображение полного размера)
Шаг 2. Определение количества продуктов для каждой категории
После завершения разметки Repeater и DataList мы готовы привязать данные категории к элементу управления Repeater. Однако, как показано в маркированном списке категорий на рис. 1, помимо имени каждой категории, необходимо также отобразить количество продуктов, связанных с категорией. Чтобы получить доступ к этой информации, можно:
- Определите эти сведения из класса кодовой части страницы ASP.NET. Учитывая конкретное
categoryID
, можно определить количество связанных продуктов, вызвавProductsBLL
метод классаGetProductsByCategoryID(categoryID)
. Этот метод возвращаетProductsDataTable
объект, свойство которогоCount
указывает, сколькоProductsRow
s существует, а именно количество продуктов для указанногоcategoryID
. Мы можем создатьItemDataBound
обработчик событий для повторителя, который для каждой категории, привязанной к повторителеру, вызываетProductsBLL
метод классаGetProductsByCategoryID(categoryID)
и включает его число в выходные данные. CategoriesDataTable
Обновите типизированный набор данных, чтобы включитьNumberOfProducts
столбец. Затем мы можем обновитьGetCategories()
метод вCategoriesDataTable
списке, чтобы включить эти сведения или, кроме того, оставитьGetCategories()
как есть и создать новыйCategoriesDataTable
метод.GetCategoriesAndNumberOfProducts()
Давайте рассмотрим оба этих метода. Первый подход проще реализовать, так как нам не нужно обновлять уровень доступа к данным; однако для этого требуется больше взаимодействия с базой данных. Вызов метода класса GetProductsByCategoryID(categoryID)
в обработчике ItemDataBound
событий добавляет дополнительный вызов ProductsBLL
базы данных для каждой категории, отображаемой в повторителере. В этом методе есть вызовы базы данных N + 1, где N — это количество категорий, отображаемых в повторителье. При втором подходе счетчик продуктов возвращается с информацией о каждой категории из CategoriesBLL
метода класса GetCategories()
(или GetCategoriesAndNumberOfProducts()
), что приводит к одной поездке в базу данных.
Определение количества продуктов в обработчике событий ItemDataBound
Определение количества продуктов для каждой категории в обработчике событий Repeater ItemDataBound
не требует каких-либо изменений в существующем уровне доступа к данным. Все изменения можно вносить непосредственно на CategoriesAndProducts.aspx
странице. Начните с добавления нового объекта ObjectDataSource с именем CategoriesDataSource
с помощью смарт-тега Repeater. Затем настройте CategoriesDataSource
ObjectDataSource, чтобы он извлекал данные из CategoriesBLL
метода класса GetCategories()
.
Рис. 3. Настройка ObjectDataSource для использования CategoriesBLL
метода класса GetCategories()
(щелкните, чтобы просмотреть изображение полного размера)
Каждый элемент в Categories
повторитее должен быть щелкаемым и при щелчке, чтобы CategoryProducts
dataList отображал эти продукты для выбранной категории. Это можно сделать, сделав каждую категорию гиперссылкой, связываясь с этой же страницей (CategoriesAndProducts.aspx
), но передавая CategoryID
через строку запросов, как мы видели в предыдущем руководстве. Преимущество этого подхода заключается в том, что страница, отображающая продукты определенной категории, может быть закладок и индексирована поисковой системой.
Кроме того, мы можем сделать каждую категорию linkButton, которая является подходом, который мы будем использовать для этого руководства. LinkButton отображается в браузере пользователя в виде гиперссылки, но при щелчке вызывает обратную передачу; При обратной отправке необходимо обновить объект ObjectDataSource DataList, чтобы отобразить эти продукты, принадлежащие выбранной категории. В этом руководстве использование гиперссылки имеет больше смысла, чем использование LinkButton; однако могут быть и другие сценарии, в которых использование LinkButton является более выгодным. Хотя подход к гиперссылкам идеально подходит для этого примера, давайте рассмотрим использование LinkButton. Как мы увидим, использование LinkButton представляет некоторые проблемы, которые не будут возникать в противном случае с гиперссылкой. Таким образом, использование LinkButton в этом руководстве поможет выделить эти проблемы и предоставить решения для этих сценариев, в которых мы можем использовать LinkButton вместо гиперссылки.
Примечание.
Рекомендуется повторить это руководство с помощью элемента управления HyperLink или <a>
элемента вместо LinkButton.
В следующей разметке показан декларативный синтаксис для повторителятеля и ObjectDataSource. Обратите внимание, что шаблоны Повторитетеля отображают маркированный список с каждым элементом в виде LinkButton:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory" /></li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Примечание.
В этом руководстве повторитель должен иметь состояние представления (обратите внимание на пропуск EnableViewState="False"
декларативного синтаксиса повторителя). На шаге 3 мы создадим обработчик событий для события Repeater ItemCommand
, в котором мы обновим коллекцию ObjectDataSource SelectParameters
DataList. Однако повторитель ItemCommand
не будет запускаться, если состояние представления отключено.
LinkButton со значением ID
ViewCategory
свойства не имеет его Text
набора свойств. Если бы мы только что хотели отобразить имя категории, мы бы задали свойство Text декларативно с помощью синтаксиса привязки данных, например:
<asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# Eval("CategoryName") %>' />
Однако мы хотим показать имя категории и количество продуктов, принадлежащих этой категории. Эти сведения можно получить из обработчика событий Repeater ItemDataBound
, выполнив вызов ProductBLL
метода класса GetCategoriesByProductID(categoryID)
и определив, сколько записей возвращаются в результате ProductsDataTable
, как показано в следующем коде:
protected void Categories_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// Make sure we're working with a data item...
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Reference the CategoriesRow instance bound to this RepeaterItem
Northwind.CategoriesRow category =
(Northwind.CategoriesRow) ((System.Data.DataRowView) e.Item.DataItem).Row;
// Determine how many products are in this category
NorthwindTableAdapters.ProductsTableAdapter productsAPI =
new NorthwindTableAdapters.ProductsTableAdapter();
int productCount =
productsAPI.GetProductsByCategoryID(category.CategoryID).Count;
// Reference the ViewCategory LinkButton and set its Text property
LinkButton ViewCategory = (LinkButton)e.Item.FindControl("ViewCategory");
ViewCategory.Text =
string.Format("{0} ({1:N0})", category.CategoryName, productCount);
}
}
Мы начнем с того, чтобы мы работали с элементом данных (один из которых ItemType
или) и ссылаемся на CategoriesRow
экземпляр, который только что привязан к текущемуRepeaterItem
.AlternatingItem
Item
Затем мы определим количество продуктов для этой категории, создав экземпляр ProductsBLL
класса, вызвав его GetCategoriesByProductID(categoryID)
метод и определив количество записей, возвращаемых с помощью Count
свойства. Наконец, ViewCategory
LinkButton в ItemTemplate имеет ссылки, а его Text
свойство имеет значение CategoryName (NumberOfProductsInCategory), где NumberOfProductsInCategory форматируется как число с нуля десятичными знаками.
Примечание.
Кроме того, мы могли бы добавить функцию форматирования в класс кода ASP.NET страницы, который принимает категории CategoryName
и значения и CategoryID
возвращает CategoryName
сцепленное число продуктов в категории (как определено путем вызова GetCategoriesByProductID(categoryID)
метода). Результаты такой функции форматирования могут быть декларативно назначены свойству Text LinkButton, заменяя необходимость обработчика ItemDataBound
событий. Дополнительные сведения об использовании функций форматирования см. в руководстве по использованию templateFields в элементе управления GridView или форматировании DataList и Repeater на основе данных.
После добавления этого обработчика событий проверьте страницу через браузер. Обратите внимание, как каждая категория указана в маркированном списке, отображая имя категории и количество продуктов, связанных с категорией (см. рис. 4).
Рис. 4. Отображаются имя и количество продуктов каждой категории (щелкните, чтобы просмотреть изображение полного размера)
CategoriesDataTable
Обновление иCategoriesTableAdapter
включение количества продуктов для каждой категории
Вместо определения количества продуктов для каждой категории, привязанных к повторителе, мы можем оптимизировать этот процесс, изменив CategoriesDataTable
уровень доступа к данным, CategoriesTableAdapter
чтобы включить эти сведения в собственном коде. Для этого необходимо добавить новый столбец для CategoriesDataTable
хранения количества связанных продуктов. Чтобы добавить новый столбец в DataTable, откройте типизированный набор данных (),App_Code\DAL\Northwind.xsd
щелкните правой кнопкой мыши dataTable, чтобы изменить, и нажмите кнопку "Добавить / Столбец". Добавьте новый столбец на CategoriesDataTable
рис. 5.
Рис. 5. Добавление нового столбца в CategoriesDataSource
столбец (щелкните, чтобы просмотреть изображение полного размера)
При этом будет добавлен новый столбец с именем Column1
, который можно изменить, просто введя другое имя. Переименуйте этот новый столбец NumberOfProducts
в . Затем необходимо настроить свойства этого столбца. Щелкните новый столбец и перейдите к окно свойств. Измените свойство столбца DataType
на System.String
System.Int32
и задайте ReadOnly
для свойства True
значение , как показано на рис. 6.
Рис. 6. Задание DataType
и ReadOnly
свойства нового столбца
Хотя теперь столбец CategoriesDataTable
имеется NumberOfProducts
, его значение не задано ни одной из соответствующих запросов TableAdapter. Мы можем обновить GetCategories()
метод для возврата этих сведений, если мы хотим, чтобы такие сведения возвращались каждый раз, когда извлекается информация о категории. Если, однако, нам нужно только получить количество связанных продуктов для категорий в редких экземплярах (например, только для этого руководства), то мы можем оставить GetCategories()
как есть и создать новый метод, возвращающий эту информацию. Давайте будем использовать этот последний подход, создав новый метод с именем GetCategoriesAndNumberOfProducts()
.
Чтобы добавить этот новый GetCategoriesAndNumberOfProducts()
метод, щелкните правой кнопкой мыши CategoriesTableAdapter
и выберите команду "Создать запрос". Откроется мастер настройки запросов TableAdapter, который мы использовали несколько раз в предыдущих руководствах. Для этого метода запустите мастер, указав, что запрос использует нерегламентированную инструкцию SQL, которая возвращает строки.
Рис. 7. Создание метода с помощью инструкции AD-Hoc SQL (щелкните, чтобы просмотреть изображение полного размера)
Рис. 8. Инструкция SQL возвращает строки (щелкните, чтобы просмотреть изображение полного размера)
Следующий экран мастера предложит нам использовать запрос. Чтобы вернуть каждую категорию CategoryID
и CategoryName
Description
поля, а также количество продуктов, связанных с категорией, используйте следующую SELECT
инструкцию:
SELECT CategoryID, CategoryName, Description,
(SELECT COUNT(*) FROM Products p WHERE p.CategoryID = c.CategoryID)
as NumberOfProducts
FROM Categories c
Рис. 9. Указание используемого запроса (щелкните, чтобы просмотреть изображение полного размера)
Обратите внимание, что вложенный запрос, вычисляющий количество продуктов, связанных с категорией, называется псевдонимом NumberOfProducts
. Это сопоставление именования приводит к тому, что значение, возвращаемое этим вложенным запросом, будет связано с столбцом CategoriesDataTable
s NumberOfProducts
.
После ввода этого запроса последний шаг — выбрать имя нового метода. Используйте FillWithNumberOfProducts
и GetCategoriesAndNumberOfProducts
для заполнения dataTable и возвращайте шаблоны DataTable соответственно.
Рис. 10. Назовите методы FillWithNumberOfProducts
New TableAdapter и GetCategoriesAndNumberOfProducts
(Щелкните, чтобы просмотреть изображение полного размера)
На этом этапе уровень доступа к данным был расширен, чтобы включить количество продуктов на категорию. Так как весь уровень презентации направляет все вызовы DAL через отдельный уровень бизнес-логики, необходимо добавить соответствующий GetCategoriesAndNumberOfProducts
метод в CategoriesBLL
класс:
[System.ComponentModel.DataObjectMethodAttribute
(System.ComponentModel.DataObjectMethodType.Select, false)]
public Northwind.CategoriesDataTable GetCategoriesAndNumberOfProducts()
{
return Adapter.GetCategoriesAndNumberOfProducts();
}
После завершения DAL и BLL мы готовы привязать эти данные к Categories
повторитею в CategoriesAndProducts.aspx
! Если вы уже создали ObjectDataSource для повторителя из раздела "Определение количества продуктов" в ItemDataBound
разделе обработчика событий, удалите этот объект ObjectDataSource и удалите параметр свойства Repeater, DataSourceID
а также разместите событие Repeater ItemDataBound
из обработчика событий, удалив Handles Categories.OnItemDataBound
синтаксис в классе ASP.NET кода программной части.
При обратном выполнении повторяющегося элемента в исходном состоянии добавьте новый объект ObjectDataSource с помощью CategoriesDataSource
смарт-тега Repeater. Настройте ObjectDataSource для использования CategoriesBLL
класса, но вместо использования GetCategories()
метода используйте GetCategoriesAndNumberOfProducts()
его (см. рис. 11).
Рис. 11. Настройка ObjectDataSource для использования GetCategoriesAndNumberOfProducts
метода (щелкните, чтобы просмотреть изображение полного размера)
Затем обновите свойство ItemTemplate
LinkButton Text
декларативно с помощью синтаксиса привязки данных и включает CategoryName
как поля данных, так и NumberOfProducts
поля данных. Полная декларативная разметка для повторителя и CategoriesDataSource
ObjectDataSource:
<asp:Repeater ID="Categories" runat="server" DataSourceID="CategoriesDataSource">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li><asp:LinkButton runat="server" ID="ViewCategory"
Text='<%# String.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>' />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategoriesAndNumberOfProducts" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
Выходные данные, отрисовываемые путем обновления DAL, чтобы включить NumberOfProducts
столбец, совпадают с подходом ItemDataBound
обработчика событий (см. рисунок 4, чтобы увидеть снимок экрана повторителя с именами категорий и числом продуктов).
Шаг 3. Отображение выбранных продуктов категории
На этом этапе у нас есть Categories
повторитель, отображающий список категорий, а также количество продуктов в каждой категории. Повторитель использует LinkButton для каждой категории, которая при щелчке вызывает обратную передачу, в какой момент необходимо отобразить эти продукты для выбранной категории в CategoryProducts
DataList.
Одна из проблем с нами заключается в том, как отобразить DataList только те продукты для выбранной категории. В руководстве master/Details Using a Selectable Master GridView с руководством DetailsView мы узнали, как создать GridView, строки которого можно выбрать, с выбранными сведениями строки, отображаемыми в DetailsView на той же странице. GridView s ObjectDataSource возвращает сведения обо всех продуктах, использующих ProductsBLL
метод s GetProducts()
, а объект ObjectDataSource DetailsView извлекает сведения о выбранном продукте GetProductsByProductID(productID)
с помощью метода. Значение productID
параметра было предоставлено декларативно путем связывания его со значением свойства GridView SelectedValue
. К сожалению, ретранслятор не имеет SelectedValue
свойства и не может служить источником параметров.
Примечание.
Это одна из этих проблем, которые появляются при использовании LinkButton в повторитее. Если вместо этого мы использовали гиперссылку для передачи через CategoryID
строку запроса, мы могли бы использовать это поле QueryString в качестве источника значения параметра.
Прежде чем беспокоиться о отсутствии SelectedValue
свойства для повторителя, давайте сначала привязать DataList к ObjectDataSource и указать его ItemTemplate
.
Из смарт-тега DataList выберите добавить новый объект ObjectDataSource с именем CategoryProductsDataSource
и настроить его для использования ProductsBLL
метода класса GetProductsByCategoryID(categoryID)
. Так как DataList в этом руководстве предоставляет интерфейс только для чтения, вы можете задать раскрывающийся список на вкладках INSERT, UPDATE и DELETE (Нет).
Рис. 12. Настройка метода ObjectDataSource для использования ProductsBLL
метода класса GetProductsByCategoryID(categoryID)
(щелкните, чтобы просмотреть изображение полного размера)
GetProductsByCategoryID(categoryID)
Так как метод ожидает входной параметр (categoryID
), мастер настройки источника данных позволяет указать источник параметров. Если категории были перечислены в GridView или DataList, мы задали раскрывающийся список источника параметров для элемента управления и ControlID ID
для веб-элемента управления данными. Однако, так как повторитель не имеет SelectedValue
свойства, его нельзя использовать в качестве источника параметров. Если проверить, вы увидите, что раскрывающийся список ControlID содержит только один элемент управления ID``CategoryProducts
, ID
список DataList.
Теперь задайте раскрывающийся список источника параметров значение None. В конечном итоге мы программно назначим это значение параметра, когда категория LinkButton щелкается в повторе.
Рис. 13. Не указывайте источник параметров для categoryID
параметра (щелкните, чтобы просмотреть изображение полного размера)
После завершения работы мастера настройки источника данных Visual Studio автоматически создает s ItemTemplate
DataList. Замените этот параметр по умолчанию ItemTemplate
шаблоном, используемым в предыдущем руководстве, а также задайте для свойства DataList RepeatColumns
значение 2. После внесения этих изменений декларативная разметка для DataList и связанного объекта ObjectDataSource должна выглядеть следующим образом:
<asp:DataList ID="CategoryProducts" runat="server" DataKeyField="ProductID"
DataSourceID="CategoryProductsDataSource" RepeatColumns="2"
EnableViewState="False">
<ItemTemplate>
<h5><%# Eval("ProductName") %></h5>
<p>
Supplied by <%# Eval("SupplierName") %><br />
<%# Eval("UnitPrice", "{0:C}") %>
</p>
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="CategoryProductsDataSource"
OldValuesParameterFormatString="original_{0}" runat="server"
SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
<SelectParameters>
<asp:Parameter Name="categoryID" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
CategoryProductsDataSource
В настоящее время параметр ObjectDataSource categoryID
никогда не задан, поэтому при просмотре страницы продукты не отображаются. То, что нам нужно сделать, это значение параметра задано в зависимости от CategoryID
категории, щелкнув ее в репетиторе. Это представляет две проблемы: во-первых, как определить, когда linkButton в репетиторе ItemTemplate
был щелкнун; и во-вторых, как определить CategoryID
соответствующую категорию, чей LinkButton был щелкнун?
LinkButton, например элементы управления Button и ImageButton, имеют Click
событие и Command
событие. Это Click
событие предназначено для того, чтобы просто отметить, что linkButton был щелкнун. Иногда, однако, помимо отметить, что LinkButton был щелкнун, мы также должны передать некоторую дополнительную информацию обработчику событий. Если это так, свойства LinkButton CommandName
CommandArgument
можно назначить эти дополнительные сведения. Затем, когда элемент LinkButton щелкается, его Command
событие запускается (вместо события Click
), а обработчик событий передает значения CommandName
и CommandArgument
свойства.
Command
При возникновении события в шаблоне в повторяющемся объекте ItemCommand
событие выполняется и передается CommandName
значение и CommandArgument
значения нажатия кнопки LinkButton (или Button или ImageButton). Таким образом, чтобы определить, когда категория LinkButton в репетиторе была щелкнуна, необходимо выполнить следующие действия:
CommandName
Присвойте свойству LinkButton в репетитореItemTemplate
некоторое значение (я использовал ListProducts). Задав этоCommandName
значение, событие LinkButton запускается при щелчке LinkButtonCommand
.- Задайте свойству LinkButton
CommandArgument
значение текущего элементаCategoryID
. - Создайте обработчик событий для события Repeater
ItemCommand
. В обработчике событий задайтеCategoryProductsDataSource
параметр ObjectDataSourceCategoryID
значение переданногоCommandArgument
объекта.
ItemTemplate
Следующая разметка для повторителя категорий реализует шаги 1 и 2. Обратите внимание, как CommandArgument
значение назначается элементу CategoryID
данных с помощью синтаксиса привязки данных:
<ItemTemplate>
<li>
<asp:LinkButton CommandName="ListProducts" runat="server"
CommandArgument='<%# Eval("CategoryID") %>' ID="ViewCategory"
Text='<%# string.Format("{0} ({1:N0})", _
Eval("CategoryName"), Eval("NumberOfProducts")) %>'>
</asp:LinkButton>
</li>
</ItemTemplate>
При создании обработчика ItemCommand
событий рекомендуется всегда сначала проверить входящие CommandName
значения, так как любое событие, вызываемое любой Command
кнопкой, LinkButton или ImageButton в повторитее, приведет ItemCommand
к возникновению события. Хотя в настоящее время у нас есть только один такой LinkButton сейчас, в будущем мы (или другой разработчик в нашей команде) можем добавить дополнительные веб-элементы управления кнопки в повторитель, который при нажатии вызывает тот же ItemCommand
обработчик событий. Поэтому рекомендуется всегда проверять CommandName
свойство и выполнять только программную логику, если она соответствует ожидаемому значению.
Убедившись, что переданное CommandName
значение равно ListProducts, обработчик событий назначает CategoryProductsDataSource
параметр ObjectDataSource CategoryID
значению переданного CommandArgument
объекта. Это изменение объекта ObjectDataSource SelectParameters
автоматически приводит к повторной привязке DataList к источнику данных, отображая продукты для новой выбранной категории.
protected void Categories_ItemCommand(object source, RepeaterCommandEventArgs e)
{
// If it's the "ListProducts" command that has been issued...
if (string.Compare(e.CommandName, "ListProducts", true) == 0)
{
// Set the CategoryProductsDataSource ObjectDataSource's CategoryID parameter
// to the CategoryID of the category that was just clicked (e.CommandArgument)...
CategoryProductsDataSource.SelectParameters["CategoryID"].DefaultValue =
e.CommandArgument.ToString();
}
}
С помощью этих дополнений наш учебник завершен! Проверьте его в браузере. На рисунке 14 показан экран при первом посещении страницы. Так как категория еще не выбрана, продукты не отображаются. Щелкнув категорию, например "Создать", отображаются эти продукты в категории "Продукт" в представлении двух столбцов (см. рис. 15).
Рис. 14. При первом посещении страницы не отображаются продукты (щелкните, чтобы просмотреть изображение полного размера)
Рис. 15. Выбор категории "Создание категорий" содержит соответствующие продукты справа (щелкните, чтобы просмотреть изображение полного размера)
Итоги
Как мы видели в этом руководстве, и предыдущие отчеты master/detail могут быть распределены по двум страницам или объединяться на одну. Однако отображение отчета master/details на одной странице представляет некоторые проблемы, связанные с тем, как лучше всего макетировать основные и подробные записи на странице. В руководстве master /Details Using a Selectable Master GridView with a DetailsView tutorial we had the details records the master records. В этом руководстве мы использовали методы CSS для плавания основных записей слева от сведений.
Наряду с отображением отчетов master/details, мы также имели возможность изучить, как получить количество продуктов, связанных с каждой категорией, а также как выполнять логику на стороне сервера при щелчке LinkButton (или Button или ImageButton) в повторяющемся объекте.
В этом руководстве мы завершаем изучение основных и подробных отчетов с помощью DataList и Repeater. В следующем наборе учебников показано, как добавить возможности редактирования и удаления в элемент управления DataList.
Счастливое программирование!
Дополнительные материалы
Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:
- Руководство по плавающему css-элементам с помощью CSS
- Размещение дополнительных сведений о расположении элементов с помощью CSS
- Размещение содержимого с помощью HTML с помощью
<table>
s и других элементов HTML для размещения
Об авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 2.0 в 24 часах. Он может быть достигнут в mitchell@4GuysFromRolla.com. или через его блог, который можно найти на http://ScottOnWriting.NET.
Особое спасибо
Эта серия учебников была проверена многими полезными рецензентами. Ведущий рецензент этого руководства был Зак Джонс. Хотите просмотреть мои предстоящие статьи MSDN? Если да, упадите меня линию в mitchell@4GuysFromRolla.com.