Фильтрация "Основной/подробности" на двух страницах (C#)Master/Detail Filtering Across Two Pages (C#)

по Скотт Митчеллby Scott Mitchell

Скачивание примера приложения или Загрузка PDF-файлаDownload Sample App or Download PDF

В этом учебнике рассматривается разделение отчета «основной/подробности» на две страницы.In this tutorial we look at how to separate a master/detail report across two pages. На главной странице мы используем элемент управления Repeater для отображения списка категорий, при щелчке которого пользователь перейдет на страницу "сведения", где в DataList в двух столбцах отображаются продукты, принадлежащие выбранной категории.In the "master" page we use a Repeater control to render a list of categories that, when clicked, will take the user to the "details" page where a two-column DataList shows those products belonging to the selected category.

ВведениеIntroduction

В предыдущем учебном курсе мы увидели, как отображать отчеты «основной/подробности» на одной веб-странице с помощью элементов управления DropDownList для отображения «главных» записей и элементов управления DataList для отображения «сведений».In the preceding tutorial we saw how to display master/detail reports in a single web page using DropDownLists to display the "master" records and a DataList to display the "details." Другим распространенным шаблоном, используемым для отчетов «основной/подробности», является запись основных записей на одной веб-странице и сведения о другом.Another common pattern used for master/detail reports is to have the master records on one web page and the details on another. В предыдущем примере фильтрации "основной/подробности" в двух страницах мы рассматривали этот шаблон с помощью элемента управления GridView для отображения всех поставщиков в системе.In the earlier Master/Detail Filtering Across Two Pages tutorial, we examined this pattern using a GridView to display all of the suppliers in the system. Этот GridView включал в себя HyperLinkField, который отображается в виде ссылки на вторую страницу, передавая SupplierID в строке запроса.This GridView included a HyperLinkField, which rendered as a link to a second page, passing along the SupplierID in the querystring. На второй странице используется GridView для перечисления продуктов, предоставляемых выбранным поставщиком.The second page used a GridView to list those products provided by the selected supplier.

Такие Многостраничные отчеты «основной/подробности» могут быть выполнены также с помощью элементов управления DataList и Repeater.Such two-page master/detail reports can be accomplished using DataList and Repeater controls as well. Единственное отличие заключается в том, что ни DataList, ни Repeater не поддерживают элемент управления HyperLinkField.The only difference is that neither the DataList nor the Repeater provides support for the HyperLinkField control. Вместо этого необходимо добавить веб-элемент управления HyperLink или элемент HTML Anchor (<a>) в ItemTemplateэлемента управления.Instead, we must add a HyperLink Web control or an anchor HTML element (<a>) within the control's ItemTemplate. Затем можно настроить свойство NavigateUrl гиперссылки или атрибут href привязки с помощью декларативных или программных подходов.The HyperLink's NavigateUrl property or the anchor's href attribute can then be customized using declarative or programmatic approaches.

В этом учебнике мы рассмотрим пример, который перечисляет категории в маркированном списке на одной странице с помощью элемента управления Repeater.In this tutorial we'll explore an example that lists the categories in a bulleted list on one page using a Repeater control. Каждый элемент списка будет включать имя и описание категории, а имя категории отображается как ссылка на вторую страницу.Each list item will include the category's name and description, with the category name displayed as a link to a second page. Если щелкнуть эту ссылку, пользователь перенесет на вторую страницу, где в DataList будут показаны продукты, принадлежащие к выбранной категории.Clicking on this link will whisk the user to the second page, where a DataList will show those products that belong to the selected category.

Шаг 1. Отображение категорий в маркированном спискеStep 1: Displaying the Categories in a Bulleted List

Первый шаг при создании отчета «основной/подробности» начинается с отображения «главных» записей.The first step in creating any master/detail report is to start by displaying the "master" records. Поэтому нашей первой задачей является отображение категорий на странице «Главная».Therefore, our first task is to display the categories in the "master" page. Откройте страницу CategoryListMaster.aspx в папке DataListRepeaterFiltering, добавьте элемент управления Repeater и в смарт-теге выберите Добавить новый объект ObjectDataSource.Open the CategoryListMaster.aspx page in the DataListRepeaterFiltering folder, add a Repeater control, and, from the smart tag, opt to add a new ObjectDataSource. Настройте новый элемент ObjectDataSource таким образом, чтобы он обращается к своим данным из метода GetCategories класса CategoriesBLL (см. рис. 1).Configure the new ObjectDataSource so that it accesses its data from the CategoriesBLL class's GetCategories method (see Figure 1).

настроить ObjectDataSource для использования метода Categories класса CategoriesBLLConfigure the ObjectDataSource to Use the CategoriesBLL Class's GetCategories Method

Рис. 1. Настройка ObjectDataSource для использования метода GetCategories класса CategoriesBLL (щелкните, чтобы просмотреть изображение с полным размером)Figure 1: Configure the ObjectDataSource to Use the CategoriesBLL Class's GetCategories Method (Click to view full-size image)

Затем определите шаблоны Repeater таким образом, чтобы имя и описание каждой категории отображались как элемент в маркированном списке.Next, define the Repeater's templates such that it displays each category name and description as an item in a bulleted list. Давайте еще не будем беспокоиться о том, что каждая категория имеет ссылку на страницу сведений.Let's not yet worry about having each category link to the details page. Ниже показана декларативная разметка для элемента управления Repeater и ObjectDataSource:The following shows the declarative markup for the Repeater and ObjectDataSource:

<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource1"
    EnableViewState="False">
    <HeaderTemplate>
        <ul>
    </HeaderTemplate>
 
    <ItemTemplate>
        <li><%# Eval("CategoryName") %> - <%# Eval("Description") %></li>
    </ItemTemplate>
 
    <FooterTemplate>
        </ul>
    </FooterTemplate>
</asp:Repeater>
 
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

После завершения этой разметки уделите время для просмотра хода выполнения через браузер.With this markup complete, take a moment to view our progress through a browser. Как показано на рис. 2, элемент Repeater отображается в виде маркированного списка, в котором указаны имя и описание каждой категории.As Figure 2 shows, the Repeater renders as a bulleted list showing each category's name and description.

каждая категория отображается как маркированный элемент спискаEach Category is Displayed as a Bulleted List Item

Рис. 2. Каждая категория отображается как маркированный элемент списка (щелкните, чтобы просмотреть изображение с полным размером)Figure 2: Each Category is Displayed as a Bulleted List Item (Click to view full-size image)

Чтобы разрешить пользователю отображать сведения об определенной категории, необходимо добавить ссылку на каждый маркированный список, при щелчке которого пользователь перейдет на вторую страницу (ProductsForCategoryDetails.aspx).To allow a user to display the "details" information for a given category, we need to add a link to each bulleted list item that, when clicked, will take the user to the second page (ProductsForCategoryDetails.aspx). На этой второй странице будут отображаться продукты для выбранной категории с помощью DataList.This second page will then display the products for the selected category using a DataList. Чтобы определить категорию, для которой была нажата ссылка, необходимо передать CategoryID на вторую страницу с помощью какого-либо механизма.In order to determine the category whose link was clicked, we need to pass the clicked category's CategoryID to the second page through some mechanism. Самый простой и простой способ переносить скалярные данные с одной страницы на другую — через строку запроса, которая является вариантом, который мы будем использовать в этом учебнике.The simplest, most straightforward way to transfer scalar data from one page to another is through the querystring, which is the option we'll use in this tutorial. В частности, на странице ProductsForCategoryDetails.aspx будет считаться, что выбранное categoryID значение передается через поле QueryString с именем CategoryID.In particular, the ProductsForCategoryDetails.aspx page will expect the selected categoryID value to be passed through a querystring field named CategoryID. Например, чтобы просмотреть продукты для категории «напитки» с CategoryID 1, пользователь будет посещать ProductsForCategoryDetails.aspx?CategoryID=1.For example, to view the products for the Beverages category, which has a CategoryID of 1, a user would visit ProductsForCategoryDetails.aspx?CategoryID=1.

Чтобы создать гиперссылку для каждого элемента маркированного списка в элементе управления Repeater, необходимо добавить в ItemTemplateэлемент Web Control HyperLink или HTML Anchor (<a>).To create a hyperlink for each bulleted list item in the Repeater we need to either add a HyperLink Web control or an HTML anchor element (<a>) to the ItemTemplate. В сценариях, где гиперссылка отображается одинаково для каждой строки, любой из этих подходов будет достаточно.In scenarios where the hyperlink is displayed the same for each row, either approach will suffice. Для повторяющихся элементов я предпочитаю использовать элемент Anchor.For Repeaters, I prefer using the anchor element. Чтобы использовать элемент Anchor, обновите ItemTemplate элемента Repeater на:To use the anchor element, update the Repeater's ItemTemplate to:

<li>
    <a href='ProductsForCategoryDetails.aspx?CategoryID=<%# Eval("CategoryID") %>'>
        <%# Eval("CategoryName") %>
    </a> - <%# Eval("Description") %>
</li>

Обратите внимание, что CategoryID можно внедрить непосредственно в атрибут href элемента привязки. Тем не менее, для этого необходимо ограничить значение href атрибута апострофами (и кавычками), так как метод Eval в атрибуте href отделяет строку ("CategoryID") кавычками.Note that the CategoryID can be injected directly within the anchor element's href attribute; however, to do so be certain to delimit the href attribute's value with apostrophes (and note quotation marks) since the Eval method within the href attribute delimits its string ("CategoryID") with quotation marks. Вместо этого можно использовать веб-элемент управления HyperLink:Alternatively, a HyperLink Web control can be used instead:

<li>
    <asp:HyperLink runat="server" Text='<%# Eval("CategoryName") %>'
        NavigateUrl='<%# "ProductsForCategoryDetails.aspx?CategoryID=" &
            Eval("CategoryID") %>'>
    </asp:HyperLink>
    - <%# Eval("Description") %>
</li>

Обратите внимание на то, как статическая часть URL-адреса — ProductsForCategoryDetails.aspx?CategoryID — добавляется к результату Eval("CategoryID") непосредственно в синтаксисе привязки данных с помощью сцепления строк.Note how the static portion of the URL — ProductsForCategoryDetails.aspx?CategoryID — is appended to the result of Eval("CategoryID") directly within the databinding syntax using string concatenation.

Одним из преимуществ использования элемента управления HyperLink является возможность программного доступа к нему из обработчика ItemDataBound событий Repeater, если это необходимо.One benefit of using the HyperLink control is that it can be programmatically accessed from the Repeater's ItemDataBound event handler, if needed. Например, можно отобразить имя категории как текст, а не как ссылку для категорий без связанных продуктов.For example, you might want to display the category name as text rather than as a link for categories with no associated products. Такую проверку можно выполнить программно в обработчике событий ItemDataBound. для категорий без связанных продуктов в свойстве NavigateUrl гиперссылки может быть задана пустая строка, что приводит к отображению конкретного имени категории в виде обычного текста (а не в виде ссылки).Such a check could be programmatically performed in the ItemDataBound event handler; for categories with no associated products, the HyperLink's NavigateUrl property could be set to a blank string, thereby resulting in that particular category name rendering as plain text (rather than as a link). Дополнительные сведения о форматировании содержимого DataList и Repeater на основе программной логики с помощью обработчика событий ItemDataBound см. в статье Форматирование элементов управления DataList и Repeater на основе данных .Refer back to the Formatting the DataList and Repeater Based Upon Data tutorial for more information on formatting the DataList and Repeater's contents based on programmatic logic through the ItemDataBound event handler.

Если вы выполняете следующие функции, вы можете использовать на странице подход к элементу привязки или элементу управления HyperLink.If you are following along, feel free to use either the anchor element or HyperLink control approach in your page. Независимо от подхода при просмотре страницы в браузере каждое имя категории должно быть отображено в виде ссылки на ProductsForCategoryDetails.aspx, передавая соответствующее значение CategoryID (см. рис. 3).Regardless of the approach, when viewing the page through a browser each category name should be rendered as a link to ProductsForCategoryDetails.aspx, passing in the applicable CategoryID value (see Figure 3).

имена категорий теперь можно связать с ProductsForCategoryDetails. aspxThe Category Names Now Link to ProductsForCategoryDetails.aspx

Рис. 3. имена категорий теперь связаны с ProductsForCategoryDetails.aspx (щелкните, чтобы просмотреть изображение с полным размером)Figure 3: The Category Names Now Link to ProductsForCategoryDetails.aspx (Click to view full-size image)

Шаг 3. Перечисление продуктов, относящихся к выбранной категорииStep 3: Listing the Products that Belong to the Selected Category

По завершении страницы CategoryListMaster.aspx все готово к внедрению страницы "сведения", ProductsForCategoryDetails.aspx.With the CategoryListMaster.aspx page complete, we're ready to turn our attention to implementing the "details" page, ProductsForCategoryDetails.aspx. Откройте эту страницу, перетащите элемент управления DataList с панели инструментов в конструктор и задайте для его свойства ID значение ProductsInCategory.Open this page, drag a DataList from the Toolbox onto the Designer, and set its ID property to ProductsInCategory. Затем в смарт-теге DataList выберите Добавить на страницу новый элемент управления ObjectDataSource, назвав его ProductsInCategoryDataSource.Next, from the DataList's smart tag choose to add a new ObjectDataSource to the page, naming it ProductsInCategoryDataSource. Настройте его таким способом, чтобы он вызывал метод GetProductsByCategoryID(categoryID) класса ProductsBLL; Задайте для раскрывающихся списков на вкладках Вставка, обновление и удаление значение (нет).Configure it such that it calls the ProductsBLL class's GetProductsByCategoryID(categoryID) method; set the drop-down lists in the INSERT, UPDATE, and DELETE tabs to (None).

настроить ObjectDataSource для использования метода GetProductsByCategoryID (categoryID) класса ProductsBLLConfigure the ObjectDataSource to Use the ProductsBLL Class's GetProductsByCategoryID(categoryID) Method

Рис. 4. Настройка ObjectDataSource для использования метода GetProductsByCategoryID(categoryID) класса ProductsBLL (щелкните, чтобы просмотреть изображение с полным размером)Figure 4: Configure the ObjectDataSource to Use the ProductsBLL Class's GetProductsByCategoryID(categoryID) Method (Click to view full-size image)

Поскольку метод GetProductsByCategoryID(categoryID) принимает входной параметр ( categoryID ), мастер выбора источника данных предлагает нам возможность указать источник параметра.Since the GetProductsByCategoryID(categoryID) method accepts an input parameter (categoryID), the Choose Data Source wizard offers us an opportunity to specify the parameter's source. Задайте в качестве источника параметра значение QueryString с помощью CategoryIDQueryStringField.Set the parameter source to QueryString using the QueryStringField CategoryID.

использовать поле строки кода CategoryID в качестве источника параметраUse the Querystring Field CategoryID as the Parameter's Source

Рис. 5. Использование поля QueryString CategoryID в качестве источника параметра (щелкните, чтобы просмотреть изображение с полным размером)Figure 5: Use the Querystring Field CategoryID as the Parameter's Source (Click to view full-size image)

Как мы видели в предыдущих руководствах, после завершения работы с мастером выбор источника данных Visual Studio автоматически создает ItemTemplate для элемента управления DataList, в котором перечислены имена и значения полей данных.As we've seen in previous tutorials, after completing the Choose Data Source wizard, Visual Studio automatically creates an ItemTemplate for the DataList that lists each data field name and value. Замените этот шаблон на тот, который содержит только название продукта, поставщика и цену.Replace this template with one that lists only the product's name, supplier, and price. Также задайте для свойства RepeatColumns элемента управления DataList значение 2.Also, set the DataList's RepeatColumns property to 2. После этих изменений декларативная разметка DataList и ObjectDataSource должна выглядеть следующим образом:After these changes, your DataList and ObjectDataSource's declarative markup should look similar to the following:

<asp:DataList ID="ProductsInCategory" runat="server" DataKeyField="ProductID"
    RepeatColumns="2" DataSourceID="ProductsInCategoryDataSource"
    EnableViewState="False">
    <ItemTemplate>
        <h5><%# Eval("ProductName") %></h5>
        <p>
            Supplied by <%# Eval("SupplierName") %><br />
            <%# Eval("UnitPrice", "{0:C}") %>
        </p>
    </ItemTemplate>
</asp:DataList>
 
<asp:ObjectDataSource ID="ProductsInCategoryDataSource"
    OldValuesParameterFormatString="original_{0}" runat="server"
    SelectMethod="GetProductsByCategoryID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" QueryStringField="CategoryID"
            Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

Чтобы просмотреть эту страницу в действии, начните со страницы CategoryListMaster.aspx. затем щелкните ссылку в маркированном списке категории.To view this page in action, start from the CategoryListMaster.aspx page; next, click on a link in the categories bulleted list. В этом случае вы перейдете к ProductsForCategoryDetails.aspx, передав CategoryID через строку запроса.Doing so will take you to ProductsForCategoryDetails.aspx, passing along the CategoryID through the querystring. ProductsInCategoryDataSource ObjectDataSource в ProductsForCategoryDetails.aspx будет получать только продукты для указанной категории и отображать их в DataList, который отображает два продукта в строке.The ProductsInCategoryDataSource ObjectDataSource in ProductsForCategoryDetails.aspx will then get just those products for the specified category and display them in the DataList, which renders two products per row. На рис. 6 показан снимок экрана ProductsForCategoryDetails.aspx при просмотре напитков.Figure 6 shows a screenshot of ProductsForCategoryDetails.aspx when viewing the Beverages.

отображаются напитки, по две строкиThe Beverages are Displayed, Two per Row

Рис. 6. отображаются напитки, две на строку (щелкните, чтобы просмотреть изображение с полным размером).Figure 6: The Beverages are Displayed, Two per Row (Click to view full-size image)

Шаг 4. Отображение сведений о категории в ProductsForCategoryDetails. aspxStep 4: Displaying Category Information on ProductsForCategoryDetails.aspx

Когда пользователь щелкает категорию в CategoryListMaster.aspx, он предпринимается для ProductsForCategoryDetails.aspx и отображения продуктов, принадлежащих выбранной категории.When a user clicks on a category in CategoryListMaster.aspx, they are taken to ProductsForCategoryDetails.aspx and shown the products that belong to the selected category. Однако в ProductsForCategoryDetails.aspx нет визуальных подсказок относительно выбранной категории.However, in ProductsForCategoryDetails.aspx there are no visual cues as to what category was selected. Пользователь, который выбрал элемент напитки, но случайно щелкнул «специи», не имеет возможности выпустить свою ошибку после достижения ProductsForCategoryDetails.aspx.A user that meant to click Beverages, but accidentally clicked Condiments, has no way of realizing their mistake once they reach ProductsForCategoryDetails.aspx. Чтобы решить эту потенциальную проблему, можно отобразить сведения о выбранной категории — ее имя и описание — в верхней части страницы ProductsForCategoryDetails.aspx.To alleviate this potential problem, we can display information about the selected category — its name and description — at the top of the ProductsForCategoryDetails.aspx page.

Для этого добавьте элемент FormView над элементом управления Repeater в ProductsForCategoryDetails.aspx.To accomplish this, add a FormView above the Repeater control in ProductsForCategoryDetails.aspx. Затем добавьте новый элемент управления ObjectDataSource на страницу из смарт-тега FormView с именем CategoryDataSource и настройте его для использования метода GetCategoryByCategoryID(categoryID) класса CategoriesBLL.Next, add a new ObjectDataSource to the page from the FormView's smart tag named CategoryDataSource and configure it to use the CategoriesBLL class's GetCategoryByCategoryID(categoryID) method.

доступ к сведениям о категории с помощью метода Жеткатегорибикатегорид (categoryID) класса CategoriesBLLAccess Information about the Category through the CategoriesBLL Class's GetCategoryByCategoryID(categoryID) Method

Рис. 7. доступ к сведениям о категории с помощью метода GetCategoryByCategoryID(categoryID) класса CategoriesBLL (щелкните, чтобы просмотреть изображение с полным размером)Figure 7: Access Information about the Category through the CategoriesBLL Class's GetCategoryByCategoryID(categoryID) Method (Click to view full-size image)

Как и в случае с ProductsInCategoryDataSource ObjectDataSource, добавленным на шаге 3, мастер настройки источника данных CategoryDataSourceзапрашивает источник для входного параметра метода GetCategoryByCategoryID(categoryID).As with the ProductsInCategoryDataSource ObjectDataSource added in Step 3, the CategoryDataSource's Configure Data Source wizard prompts us for a source for the GetCategoryByCategoryID(categoryID) method's input parameter. Используйте те же параметры, что и ранее, установив для источника параметра значение QueryString, а для значения QueryStringField — CategoryID (см. рис. 5).Use the exact same settings as before, setting the parameter source to QueryString and the QueryStringField value to CategoryID (refer back to Figure 5).

После завершения работы мастера Visual Studio автоматически создает ItemTemplate, EditItemTemplateи InsertItemTemplate для FormView.After completing the wizard, Visual Studio automatically creates an ItemTemplate, EditItemTemplate, and InsertItemTemplate for the FormView. Так как мы предоставляем интерфейс только для чтения, вы можете удалить EditItemTemplate и InsertItemTemplate.Since we're providing a read-only interface, feel free to remove the EditItemTemplate and InsertItemTemplate. Кроме того, вы можете настроить ItemTemplateFormView.Also, feel free to customize the FormView's ItemTemplate. После удаления лишних шаблонов и настройки ItemTemplate декларативная разметка FormView и ObjectDataSource должна выглядеть следующим образом:After removing the superfluous templates and customizing the ItemTemplate, your FormView and ObjectDataSource's declarative markup should look similar to the following:

<asp:FormView ID="FormView1" runat="server" DataKeyNames="CategoryID"
    DataSourceID="CategoryDataSource" EnableViewState="False" Width="100%">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CategoryNameLabel" runat="server"
                Text='<%# Bind("CategoryName") %>' />
        </h3>
        <p>
            <asp:Label ID="DescriptionLabel" runat="server"
                Text='<%# Bind("Description") %>' />
        </p>
    </ItemTemplate>
</asp:FormView>
 
<asp:ObjectDataSource ID="CategoryDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategoryByCategoryID" TypeName="CategoriesBLL">
    <SelectParameters>
        <asp:QueryStringParameter Name="categoryID" Type="Int32"
            QueryStringField="CategoryID" />
    </SelectParameters>
</asp:ObjectDataSource>

На рис. 8 показан снимок экрана при просмотре этой страницы в браузере.Figure 8 shows a screen shot when viewing this page through a browser.

Note

Помимо FormView, я также добавил элемент управления HyperLink над FormView, который вернет пользователя в список категорий (CategoryListMaster.aspx).In addition to the FormView, I've also added a HyperLink control above the FormView that will take the user back to the list of categories (CategoryListMaster.aspx). Вы можете поместить эту ссылку в другое место или полностью опустить ее.Feel free to place this link elsewhere or to omit it altogether.

Сведения о категории теперь отображаются в верхней части страницыCategory Information is Now Displayed at the Top of the Page

Рис. 8. Теперь сведения о категориях отображаются в верхней части страницы (щелкните, чтобы просмотреть изображение с полным размером)Figure 8: Category Information is Now Displayed at the Top of the Page (Click to view full-size image)

Шаг 5. Отображение сообщения, если продукты не относятся к выбранной категорииStep 5: Displaying a Message if No Products Belong to the Selected Category

На CategoryListMaster.aspx странице перечислены все категории в системе, независимо от наличия связанных с ними продуктов.The CategoryListMaster.aspx page lists all categories in the system, regardless of whether there are any associated products. Если пользователь щелкает категорию без связанных продуктов, элемент управления DataList в ProductsForCategoryDetails.aspx не будет подготовлен, так как его источник данных не будет содержать никаких элементов.If a user clicks on a category with no associated products, the DataList in ProductsForCategoryDetails.aspx will not be rendered, as its data source will not have any items. Как мы видели в прошлых учебных курсах, GridView предоставляет свойство EmptyDataText, которое можно использовать для указания текстового сообщения, которое должно отображаться, если в его источнике данных нет записей.As we've seen in past tutorials, the GridView provides an EmptyDataText property that can be used to specify a text message to display if there are no records in its data source. Увы, ни элемент управления DataList, ни Repeater не имеют такого свойства.Unfortunately, neither the DataList nor Repeater has such a property.

Чтобы отобразить сообщение о том, что для выбранной категории нет соответствующих продуктов, необходимо добавить на страницу элемент управления Label, для которого в свойстве Text назначено сообщение, которое будет отображаться в случае отсутствия соответствующих продуктов.In order to display a message informing the user that there are no matching products for the selected category, we need to add a Label control to the page whose Text property is assigned the message to display in the event that there are no matching products. Затем необходимо программно задать свойство Visible в зависимости от того, содержит ли DataList какие либо элементы.We then need to programmatically set its Visible property based on whether or not the DataList contains any items.

Чтобы сделать это, начните с добавления метки под элементом управления DataList.To accomplish this, start by adding a Label beneath the DataList. Присвойте свойству ID NoProductsMessage и его свойству Text значение "отсутствуют продукты для выбранной категории..." Далее необходимо программно задать свойство Visible этой метки в зависимости от того, были ли данные привязаны к ProductsInCategory DataList.Set its ID property to NoProductsMessage and its Text property to "There are no products for the selected category…" Next, we need to programmatically set this Label's Visible property based on whether or not any data was bound to the ProductsInCategory DataList. Это назначение должно быть выполнено после привязки данных к DataList.This assignment must be made after the data has been bound to the DataList. Для элементов GridView, DetailsView и FormView можно создать обработчик событий для события DataBound элемента управления, которое срабатывает после завершения привязки данных.For the GridView, DetailsView, and FormView, we could create an event handler for the control's DataBound event, which fires after databinding has completed. Однако ни элемент управления DataList, ни Repeater не имеют доступного DataBound события.However, neither the DataList nor the Repeater has a DataBound event available.

В этом конкретном примере можно назначить свойство Visible метки в обработчике событий Page_Load, поскольку данные будут назначены элементу управления DataList до события Load страницы.For this particular example we can assign the Label's Visible property in the Page_Load event handler, since the data will have been assigned to the DataList prior to the page's Load event. Однако этот подход не будет работать в общем случае, так как данные из ObjectDataSource могут быть привязаны к DataList позже в жизненном цикле страницы.However, this approach would not work in the general case, as the data from the ObjectDataSource might be bound to the DataList later in the page's lifecycle. Например, если отображаемые данные основаны на значении в другом элементе управления, например при отображении отчета «основной/подробности» с помощью DropDownList для хранения «основных» записей, данные могут быть не привязаны к веб-элементу управления данными до тех пор, пока не будет PreRender этапа жизненного цикла страницы.For example, if the displayed data is based upon the value in another control, such as it is when displaying a master/detail report using a DropDownList to hold the "master" records, the data may not rebound to the data Web control until the PreRender stage in the page's life cycle.

Одним из решений, которые будут работать во всех случаях, является присвоение свойству Visible False в обработчике событий ItemDataBound (или ItemCreated) DataList при привязке типа элемента Item или AlternatingItem.One solution which will work for all cases is to assign the Visible property to False in the DataList's ItemDataBound (or ItemCreated) event handler when binding an item type of Item or AlternatingItem. В этом случае мы понимаем, что в источнике данных есть хотя бы один элемент данных, и поэтому может скрыть NoProductsMessage метку.In such a case we know that there is at least one data item in the data source and therefore can hide the NoProductsMessage Label. В дополнение к этому обработчику событий нам также нужен обработчик событий DataBinding элемента управления DataList, в котором мы инициализируем свойство Visible метки для True.In addition to this event handler, we also need an event handler for the DataList's DataBinding event, where we initialize the Label's Visible property to True. Так как событие DataBinding срабатывает до ItemDataBound событий, для свойства Visible метки первоначально устанавливается значение True. Однако если имеются какие бы то ни было элементы данных, для них будет задано значение False.Since the DataBinding event fires before the ItemDataBound events, the Label's Visible property will initially be set to True; if there are any data items, however, it will be set to False. Следующий код реализует эту логику:The following code implements this logic:

protected void ProductsInCategory_DataBinding(object sender, EventArgs e)
{
    // Show the Label
    NoProductsMessage.Visible = true;
}
 
protected void ProductsInCategory_ItemDataBound(object sender, DataListItemEventArgs e)
{
    // If we have a data item, hide the Label
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
        NoProductsMessage.Visible = false;
}

Все категории в базе данных Northwind связаны с одним или несколькими продуктами.All of the categories in the Northwind database are associated with one or more products. Чтобы протестировать эту функцию, я вручную настроил базу данных Northwind для этого руководства, переназначит все продукты, связанные с категорией создания (CategoryID = 7), в категорию Seafood (CategoryID = 8).To test this feature, I've manually adjusted the Northwind database for this tutorial, reassigning all products associated with the Produce category (CategoryID = 7) to the Seafood category (CategoryID = 8). Это можно сделать в обозреватель сервера, выбрав Создать запрос и используя следующую инструкцию UPDATE:This can be accomplished from the Server Explorer by choosing New Query and using the following UPDATE statement:

UPDATE Products SET
    CategoryID = 8
WHERE CategoryID = 7

После обновления базы данных вернитесь на страницу CategoryListMaster.aspx и щелкните ссылку Создать.After updating the database accordingly, return to the CategoryListMaster.aspx page and click on the Produce link. Поскольку больше нет продуктов, принадлежащих категории создать, вы должны увидеть "продукты для выбранной категории отсутствуют..." сообщение, как показано на рис. 9.Since there are no longer any products belonging to the Produce category, you should see the "There are no products for the selected category…" message, as shown in Figure 9.

отображается сообщение, если нет продуктов, принадлежащих к выбранной категорииA Message is Displayed if there are No Products Belonging to the Selected Category

Рис. 9. сообщение отображается, если нет продуктов, принадлежащих к выбранной категории (щелкните, чтобы просмотреть изображение с полным размером)Figure 9: A Message is Displayed if there are No Products Belonging to the Selected Category (Click to view full-size image)

СводкаSummary

В то время как отчеты «основной/подробности» могут отображать как основные, так и подробные записи на одной странице, во многих веб-сайтах они разделяются на две веб-страницы.While master/detail reports can display both the master and detail records on a single page, in many websites they are separated out across two web pages. В этом учебнике мы рассмотрели, как реализовать такой отчет «основной/подробности», используя категории, перечисленные в маркированном списке, с помощью повторителя на главной веб-странице и связанных продуктов, перечисленных на странице «сведения».In this tutorial we looked at how to implement such a master/detail report by having the categories listed in a bulleted list using a Repeater in the "master" web page and the associated products listed in the "details" page. Каждый элемент списка на главной веб-странице содержал ссылку на страницу сведений, переданную по значению CategoryID строки.Each list item in the master web page contained a link to the details page that passed along the row's CategoryID value.

На странице сведений получение этих продуктов для указанного поставщика осуществлялось с помощью метода GetProductsByCategoryID(categoryID) класса ProductsBLL.In the details page retrieving those products for the specified supplier was accomplished through the ProductsBLL class's GetProductsByCategoryID(categoryID) method. Значение параметра categoryID было указано декларативно с использованием значения CategoryID QueryString в качестве источника параметра.The categoryID parameter value was specified declaratively using the CategoryID querystring value as the parameter source. Мы также рассмотрели, как отобразить сведения о категории на странице сведений с помощью FormView и как отобразить сообщение, если нет продуктов, принадлежащих к выбранной категории.We also looked at how to display category details in the details page using a FormView and how to display a message if there were no products belonging to the selected category.

Поздравляем с программированием!Happy Programming!

Об автореAbout the Author

Скотт Митчелл, автор семи книг по ASP/ASP. NET и основатель 4GuysFromRolla.com, работал с веб-технологиями Майкрософт с 1998.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Скотт работает как независимый консультант, преподаватель и модуль записи.Scott works as an independent consultant, trainer, and writer. Его последняя книга — Sams обучать себя ASP.NET 2,0 за 24 часа.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Он доступен по адресу mitchell@4GuysFromRolla.com.He can be reached at mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.or via his blog, which can be found at http://ScottOnWriting.NET.

Особая благодарность...Special Thanks To…

Эта серия руководств была рассмотрена многими полезными рецензентами.This tutorial series was reviewed by many helpful reviewers. Потенциальным рецензентам для этого учебника были Зак Jones и основными рецензентами.Lead reviewers for this tutorial were Zack Jones and Liz Shulok. Хотите ознакомиться с моими будущими статьями MSDN?Interested in reviewing my upcoming MSDN articles? Если это так, расположите строку в mitchell@4GuysFromRolla.com.If so, drop me a line at mitchell@4GuysFromRolla.com.