Поделиться через


Отчет "Основной/подробности" с использованием маркированного списка основных записей с элементом управления DataList для подробных сведений (C#)

Скотт Митчелл

Скачать в формате PDF

В этом руководстве мы сжимаем двухстраничный главный или подробный отчет предыдущего руководства на одну страницу, где отображается маркированный список имен категорий слева от экрана и продукты выбранной категории справа от экрана.

Введение

В предыдущем руководстве мы рассмотрели, как разделить главный или подробный отчет на двух страницах. На главной странице мы использовали элемент управления 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 (хотя прямо сейчас оба отображаются как серые поля, так как мы еще не настроили свои источники данных или шаблоны).

Повторитель с плавающей запятой слева от 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() .

Настройка ObjectDataSource для использования метода GetCategoriesBLL класса 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.AlternatingItemItem Затем мы определим количество продуктов для этой категории, создав экземпляр 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.

Добавление нового столбца в CategoriesDataSource

Рис. 5. Добавление нового столбца в CategoriesDataSource столбец (щелкните, чтобы просмотреть изображение полного размера)

При этом будет добавлен новый столбец с именем Column1, который можно изменить, просто введя другое имя. Переименуйте этот новый столбец NumberOfProductsв . Затем необходимо настроить свойства этого столбца. Щелкните новый столбец и перейдите к окно свойств. Измените свойство столбца DataType на System.String System.Int32 и задайте ReadOnly для свойства Trueзначение , как показано на рис. 6.

Задание свойств DataType и ReadOnly нового столбца

Рис. 6. Задание DataType и ReadOnly свойства нового столбца

Хотя теперь столбец CategoriesDataTable имеется NumberOfProducts , его значение не задано ни одной из соответствующих запросов TableAdapter. Мы можем обновить GetCategories() метод для возврата этих сведений, если мы хотим, чтобы такие сведения возвращались каждый раз, когда извлекается информация о категории. Если, однако, нам нужно только получить количество связанных продуктов для категорий в редких экземплярах (например, только для этого руководства), то мы можем оставить GetCategories() как есть и создать новый метод, возвращающий эту информацию. Давайте будем использовать этот последний подход, создав новый метод с именем GetCategoriesAndNumberOfProducts().

Чтобы добавить этот новый GetCategoriesAndNumberOfProducts() метод, щелкните правой кнопкой мыши CategoriesTableAdapter и выберите команду "Создать запрос". Откроется мастер настройки запросов TableAdapter, который мы использовали несколько раз в предыдущих руководствах. Для этого метода запустите мастер, указав, что запрос использует нерегламентированную инструкцию SQL, которая возвращает строки.

Создание метода с помощью инструкции AD-Hoc SQL

Рис. 7. Создание метода с помощью инструкции AD-Hoc SQL (щелкните, чтобы просмотреть изображение полного размера)

Инструкция SQL возвращает строки

Рис. 8. Инструкция SQL возвращает строки (щелкните, чтобы просмотреть изображение полного размера)

Следующий экран мастера предложит нам использовать запрос. Чтобы вернуть каждую категорию CategoryIDи CategoryNameDescription поля, а также количество продуктов, связанных с категорией, используйте следующую 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 соответственно.

Назовите методы New TableAdapter FillWithNumberOfProducts и GetCategoriesAndNumberOfProducts

Рис. 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).

Настройка ObjectDataSource для использования метода GetCategoriesAndNumberOfProducts

Рис. 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 (Нет).

Настройка объектаDataSource для использования метода GetProductsByCategoryID(categoryID) класса ProductsBLL

Рис. 12. Настройка метода ObjectDataSource для использования ProductsBLL метода класса GetProductsByCategoryID(categoryID) (щелкните, чтобы просмотреть изображение полного размера)

GetProductsByCategoryID(categoryID) Так как метод ожидает входной параметр (categoryID), мастер настройки источника данных позволяет указать источник параметров. Если категории были перечислены в GridView или DataList, мы задали раскрывающийся список источника параметров для элемента управления и ControlID ID для веб-элемента управления данными. Однако, так как повторитель не имеет SelectedValue свойства, его нельзя использовать в качестве источника параметров. Если проверить, вы увидите, что раскрывающийся список ControlID содержит только один элемент управления ID``CategoryProducts, ID список DataList.

Теперь задайте раскрывающийся список источника параметров значение None. В конечном итоге мы программно назначим это значение параметра, когда категория LinkButton щелкается в повторе.

Не указывайте источник параметров для параметра categoryID

Рис. 13. Не указывайте источник параметров для categoryID параметра (щелкните, чтобы просмотреть изображение полного размера)

После завершения работы мастера настройки источника данных Visual Studio автоматически создает s ItemTemplateDataList. Замените этот параметр по умолчанию 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 в репетиторе была щелкнуна, необходимо выполнить следующие действия:

  1. CommandName Присвойте свойству LinkButton в репетиторе ItemTemplate некоторое значение (я использовал ListProducts). Задав это CommandName значение, событие LinkButton запускается при щелчке LinkButton Command .
  2. Задайте свойству LinkButton CommandArgument значение текущего элемента CategoryID.
  3. Создайте обработчик событий для события Repeater ItemCommand . В обработчике событий задайте CategoryProductsDataSource параметр ObjectDataSource CategoryID значение переданного 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.

Счастливое программирование!

Дополнительные материалы

Дополнительные сведения о разделах, описанных в этом руководстве, см. в следующих ресурсах:

Об авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Сэмс Учит себя ASP.NET 2.0 в 24 часах. Он может быть достигнут в mitchell@4GuysFromRolla.com. или через его блог, который можно найти на http://ScottOnWriting.NET.

Особое спасибо

Эта серия учебников была проверена многими полезными рецензентами. Ведущий рецензент этого руководства был Зак Джонс. Хотите просмотреть мои предстоящие статьи MSDN? Если да, упадите меня линию в mitchell@4GuysFromRolla.com.