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


Форматирование элементов управления DataList и Repeater в зависимости от данных (C#)

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

Загрузить PDF-файл

В этом руководстве мы рассмотрим примеры форматирования внешнего вида элементов управления DataList и Repeater с помощью функций форматирования в шаблонах или обработки события DataBound.

Введение

Как мы видели в предыдущем руководстве, DataList предлагает ряд свойств, связанных со стилем, которые влияют на его внешний вид. В частности, мы узнали, как назначать классы CSS по умолчанию свойствам DataList HeaderStyle, ItemStyle, AlternatingItemStyleи SelectedItemStyle . Помимо этих четырех свойств, DataList включает ряд других свойств, связанных со стилем, таких как Font, ForeColor, BackColorи BorderWidth. Элемент управления Repeater не содержит свойств, связанных со стилем. Любые такие параметры стиля должны быть сделаны непосредственно в разметке в шаблонах Repeater.

Однако зачастую способ форматирования данных зависит от самих данных. Например, при перечислении продуктов может потребоваться отобразить сведения о продукте светло-серым цветом шрифта, если он недоступен, или UnitsInStock выделить значение, если оно равно нулю. Как мы видели в предыдущих руководствах, GridView, DetailsView и FormView предлагают два различных способа форматирования внешнего вида на основе данных:

  • Событие DataBound создает обработчик событий для соответствующего DataBound события, которое срабатывает после привязки данных к каждому элементу (для GridView это было RowDataBound событие; для DataList и Repeater это ItemDataBound событие). В этом обработчике событий можно проверить только привязанные данные и принять решения о форматировании. Мы рассмотрели этот метод в учебнике Пользовательское форматирование на основе данных .
  • Функции форматирования в шаблонах при использовании TemplateFields в элементах управления DetailsView или GridView или шаблона в элементе управления FormView можно добавить функцию форматирования в класс кода программной части ASP.NET страницы, уровень бизнес-логики или любую другую библиотеку классов, доступную из веб-приложения. Эта функция форматирования может принимать произвольное количество входных параметров, но должна возвращать HTML-код для отрисовки в шаблоне. Функции форматирования были впервые рассмотрены в руководстве Использование TemplateFields в элементе управления GridView .

Оба этих метода форматирования доступны в элементах управления DataList и Repeater. В этом руководстве мы рассмотрим примеры использования обоих методов для обоих элементов управления.

Использование обработчикаItemDataBoundсобытий

Когда данные привязаны к DataList либо из элемента управления источником данных, либо путем программного назначения данных свойству элемента управления DataSource и вызова его DataBind() метода, возникает событие DataList DataBinding , источник данных перечисляется, и каждая запись данных привязана к DataList. Для каждой записи в источнике данных DataList создает DataListItem объект, который затем привязывается к текущей записи. Во время этого процесса DataList вызывает два события:

  • ItemCreated срабатывает после DataListItem создания
  • ItemDataBound срабатывает после привязки текущей записи к DataListItem

Ниже описан процесс привязки данных для элемента управления DataList.

  1. Срабатывает событие DataList DataBinding

  2. Данные привязаны к DataList

    Для каждой записи в источнике данных

    1. Создание DataListItem объекта
    2. Сожмите ItemCreated событие
    3. Привяжите запись к DataListItem
    4. Сожмите ItemDataBound событие
    5. Добавление в DataListItem коллекцию Items

При привязке данных к элементу управления Repeater выполняется та же последовательность шагов. Единственное отличие заключается в том, что вместо создаваемых DataListItem экземпляров repeater использует RepeaterItems.

Примечание

Проницательный читатель, возможно, заметил небольшую аномалию между последовательностью шагов, которые выполняются, когда DataList и Repeater привязаны к данным, по сравнению с привязкой GridView к данным. В конце процесса привязки данных GridView вызывает DataBound событие, однако ни элемент управления DataList, ни Repeater не имеют такого события. Это связано с тем, что элементы управления DataList и Repeater были созданы еще в ASP.NET 1.x, до того, как шаблон обработчика событий предварительного и пост-уровня стал распространенным.

Как и в GridView, одним из вариантов форматирования на основе данных является создание обработчика ItemDataBound события. Этот обработчик событий будет проверять данные, которые только что были привязаны к DataListItem или RepeaterItem , и при необходимости влиять на форматирование элемента управления.

Для элемента управления DataList изменения форматирования для всего элемента можно реализовать с помощью свойств, связанных со DataListItem стилем , к которым относятся стандартные Font, ForeColor, BackColor, CssClassи т. д. Чтобы повлиять на форматирование определенных веб-элементов управления в шаблоне DataList, необходимо программно получить доступ к их стилю и изменить их стиль. Мы узнали, как это сделать еще в учебнике Пользовательское форматирование на основе данных . Как и элемент управления Repeater, класс не имеет свойств, RepeaterItem связанных со стилем, поэтому все связанные со стилем изменения, внесенные RepeaterItem в ItemDataBound в обработчике событий, должны выполняться программным путем доступа к веб-элементам управления в шаблоне и их обновления.

ItemDataBound Так как методы форматирования для DataList и Repeater практически идентичны, в нашем примере мы сосредоточимся на использовании DataList.

Шаг 1. Отображение сведений о продукте в dataList

Прежде чем мы рассмотрим форматирование, сначала создадим страницу, которая использует DataList для отображения сведений о продукте. В предыдущем руководстве мы создали DataList, в котором ItemTemplate отображалось название, категория, поставщик, количество на единицу и цена каждого продукта. Давайте повторим эту функцию в этом руководстве. Для этого можно либо воссоздать DataList и его ObjectDataSource с нуля, либо скопировать эти элементы управления со страницы, созданной в предыдущем руководстве (Basics.aspx), и вставить их на страницу этого руководства (Formatting.aspx).

После репликации функциональных возможностей DataList и ObjectDataSource из Basics.aspx в Formatting.aspxукажите , чтобы изменить свойство DataList ID с DataList1 на более описательное ItemDataBoundFormattingExample. Затем просмотрите Список данных в браузере. Как показано на рисунке 1, единственное различие форматирования между каждым продуктом заключается в том, что цвет фона чередуется.

Продукты перечислены в элементе управления DataList

Рис. 1. Продукты перечислены в элементе управления DataList (щелкните, чтобы просмотреть полноразмерное изображение)

В этом руководстве мы отформатируем Список данных таким образом, чтобы все продукты с ценой менее 20,00 долл. США были выделены желтым цветом как название, так и цена за единицу.

Шаг 2. Программное определение значения данных в обработчике событий ItemDataBound

Так как только те продукты с ценой ниже $ 20,00 будут иметь пользовательское форматирование применено, мы должны быть в состоянии определить цену каждого продукта. При привязке данных к DataList DataList перечисляет записи в источнике данных и для каждой DataListItem записи создает экземпляр , привязывая запись источника данных к DataListItem. После привязки данных конкретной записи к текущему DataListItem объекту запускается событие DataList ItemDataBound . Мы можем создать обработчик событий для этого события, чтобы проверить значения данных для текущего DataListItem и на основе этих значений внести необходимые изменения в форматирование.

Создайте ItemDataBound событие для DataList и добавьте следующий код:

protected void ItemDataBoundFormattingExample_ItemDataBound
    (object sender, DataListItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item ||
        e.Item.ItemType == ListItemType.AlternatingItem)
    {
        // Programmatically reference the ProductsRow instance bound
        // to this DataListItem
        Northwind.ProductsRow product =
            (Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
        // See if the UnitPrice is not NULL and less than $20.00
        if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        {
            // TODO: Highlight the product's name and price
        }
    }
}

Хотя концепция и семантика обработчика событий DataList ItemDataBound те же, что и те, которые используются обработчиком событий GridView RowDataBound в учебнике Пользовательское форматирование на основе данных , синтаксис немного отличается. При возникновении события только что привязанный к данным передается в соответствующий e.Rowобработчик событий через e.Item (вместо , как в случае с обработчиком событий GridViewRowDataBound).ItemDataBoundDataListItem Обработчик событий DataList ItemDataBound срабатывает для каждой строки, добавленной в DataList, включая строки заголовков, нижних колонтитулов и строки разделителей. Однако сведения о продукте привязаны только к строкам данных. Поэтому при использовании ItemDataBound события для проверки данных, привязанных к DataList, необходимо сначала убедиться, что мы работаем с элементом данных. Это можно сделать, проверив DataListItem свойство sItemType, которое может иметь одно из следующих восьми значений:

  • AlternatingItem
  • EditItem
  • Footer
  • Header
  • Item
  • Pager
  • SelectedItem
  • Separator

Элементы Item данных DataList в и AlternatingItem``DataListItem . При условии, что мы работаем с или AlternatingItem, мы имеем Item доступ к фактическому ProductsRow экземпляру, который был привязан к текущему DataListItemобъекту . Свойство DataListItem s DataItem содержит ссылку на DataRowView объект , свойство которого Row предоставляет ссылку на фактический ProductsRow объект .

Далее мы проверка ProductsRow свойство экземпляра UnitPrice . Так как поле таблицы UnitPrice Products допускает NULL значения, прежде чем пытаться получить доступ к свойствуUnitPrice, необходимо сначала проверка, чтобы узнать, имеет NULL ли оно значение с помощью IsUnitPriceNull() метода . UnitPrice Если значение не NULLравно , мы проверка, чтобы проверить, меньше ли оно 20,00 долл. США. Если оно действительно ниже 20,00 долл. США, необходимо применить настраиваемое форматирование.

Шаг 3. Выделение названия и цены продукта

Как только мы знаем, что цена продукта менее $ 20,00, все, что остается, это выделить его название и цену. Для этого сначала необходимо программно сослаться на элементы управления Label в , ItemTemplate отображающие название и цену продукта. Затем нам нужно, чтобы они отображали желтый фон. Эти сведения о форматировании можно применить путем непосредственного изменения свойств меток BackColor (LabelID.BackColor = Color.Yellow). Однако в идеале все вопросы, связанные с отображением, должны быть выражены с помощью каскадных таблиц стилей. Фактически у нас уже есть таблица стилей, которая предоставляет требуемое форматирование, определенное в Styles.css - AffordablePriceEmphasis, которое было создано и описано в руководстве Пользовательское форматирование на основе данных .

Чтобы применить форматирование, просто присвойте свойствам двух веб-элементов управления CssClassAffordablePriceEmphasisLabel значение , как показано в следующем коде:

// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
    ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
    UnitPriceLabel.CssClass = "AffordablePriceEmphasis";

Завершив работу обработчика ItemDataBound событий, вернитесь на страницу Formatting.aspx в браузере. Как показано на рисунке 2, для этих продуктов с ценой ниже 20,00 долл. США выделены как название, так и цена.

Эти продукты менее 20,00 долл. США выделены

Рис. 2. Эти продукты менее 20,00 долл. США выделены (щелкните, чтобы просмотреть полноразмерное изображение)

Примечание

Так как DataList отображается в виде HTML <table>, его DataListItem экземпляры имеют свойства, связанные со стилем, которые можно задать для применения определенного стиля ко всему элементу. Например, если бы мы хотели выделить весь элемент желтым цветом, если его цена была меньше 20,00 долл. США, можно было бы заменить код, ссылающийся на метки, и задать их CssClass свойства следующей строкой кода: e.Item.CssClass = "AffordablePriceEmphasis" (см. рис. 3).

Однако RepeaterItem элементы , составляющие элемент управления Repeater, не предлагают таких свойств на уровне стиля. Поэтому применение настраиваемого форматирования к Repeater требует применения свойств стиля к веб-элементам управления в шаблонах Repeater, как это было показано на рисунке 2.

Весь элемент продукта выделен для продуктов до 20,00 долл. США

Рис. 3. Для продуктов под 20,00 долл. США выделен весь элемент продукта (щелкните, чтобы просмотреть полноразмерное изображение)

Использование функций форматирования из шаблона

В учебнике Использование TemplateFields в элементе управления GridView мы узнали, как использовать функцию форматирования в GridView TemplateField для применения настраиваемого форматирования на основе данных, привязанных к строкам GridView. Функция форматирования — это метод, который может быть вызван из шаблона и возвращает HTML-код, который будет выдан на его месте. Функции форматирования могут находиться в классе кода программной части страницы ASP.NET или могут быть централизованы в файлах классов в папке App_Code или в отдельном проекте библиотеки классов. Перемещение функции форматирования из класса кода программной части страницы ASP.NET идеально подходит, если вы планируете использовать одну и ту же функцию форматирования на нескольких ASP.NET страницах или в других веб-приложениях ASP.NET.

Чтобы продемонстрировать функции форматирования, пусть сведения о продукте включают текст [DISCONTINUED] рядом с названием продукта, если он не отменен. Кроме того, пусть цена выделена желтым цветом, если она меньше 20,00 долл. США (как это было в ItemDataBound примере обработчика событий); если цена составляет 20,00 долл. США или выше, пусть не отображает фактическую цену, но вместо этого текст: Вызовите ценовое предложение. На рисунке 4 показан снимок экрана со списком продуктов с примененными правилами форматирования.

Снимок экрана: продукты, перечисленные в элементе управления DataList, с ценой продуктов стоимостью более 20,00 долл. США, замененной текстом

Рис. 4. Для дорогих продуктов цена заменена текстом. Вызовите ценовое предложение (щелкните, чтобы просмотреть полноразмерное изображение)

Шаг 1. Создание функций форматирования

В этом примере нам потребуются две функции форматирования: одна отображает название продукта вместе с текстом [DISCONTINUED], если это необходимо, а другая — выделенную цену, если она меньше 20,00 долл. США, или текст . В противном случае вызовите ценовую цену. Создадим эти функции в классе кода программной части страницы ASP.NET и назовем их DisplayProductNameAndDiscontinuedStatus и DisplayPrice. Оба метода должны возвращать HTML-код для отрисовки в виде строки, и оба метода должны быть помечены Protected (или Public), чтобы вызываться из декларативной части синтаксиса страницы ASP.NET. Ниже приведен код для этих двух методов.

protected string DisplayProductNameAndDiscontinuedStatus
    (string productName, bool discontinued)
{
    // Return just the productName if discontinued is false
    if (!discontinued)
        return productName;
    else
        // otherwise, return the productName appended with the text "[DISCONTINUED]"
        return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
    // If price is less than $20.00, return the price, highlighted
    if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              product.UnitPrice.ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

Обратите внимание, что DisplayProductNameAndDiscontinuedStatus метод принимает значения productName полей данных и discontinued в виде скалярных значенийProductsRow, тогда как DisplayPrice метод принимает экземпляр (а не скалярное unitPrice значение). Любой из подходов будет работать; Однако, если функция форматирования работает со скалярными значениями, которые могут содержать значения базы данных NULL (напримерUnitPrice, ни ; ни DiscontinuedProductName допустимые NULL значения), то при обработке этих скалярных входных данных необходимо проявлять особую осторожность.

В частности, входной параметр должен иметь тип , Object так как входящее значение может быть экземпляром DBNull , а не ожидаемым типом данных. Кроме того, необходимо выполнить проверка, чтобы определить, является ли входящее значение значением базы данныхNULL. То есть, если мы хотим DisplayPrice , чтобы метод принимал цену в качестве скалярного значения, необходимо использовать следующий код:

protected string DisplayPrice(object unitPrice)
{
    // If price is less than $20.00, return the price, highlighted
    if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
        return string.Concat("<span class=\"AffordablePriceEmphasis\">",
                              ((decimal) unitPrice).ToString("C"), "</span>");
    else
        // Otherwise return the text, "Please call for a price quote"
        return "<span>Please call for a price quote</span>";
}

Обратите внимание, что unitPrice входной параметр имеет тип Object и что условный оператор был изменен, чтобы определить, является ли unitPrice он DBNull или нет. Кроме того, так как unitPrice входной параметр передается в виде Object, он должен быть приведен к десятичному значению.

Шаг 2. Вызов функции форматирования из элемента ItemTemplate dataList

После добавления функций форматирования в класс кода программной части страницы ASP.NET остается только вызвать эти функции форматирования из dataList .ItemTemplate Чтобы вызвать функцию форматирования из шаблона, разместите вызов функции в синтаксисе привязки данных:

<%# MethodName(inputParameter1, inputParameter2, ...) %>

В элементе управления Метка Веб-элемент управления DataList ItemTemplateProductNameLabel в настоящее время отображает имя продукта, присваивая его Text свойству результат <%# Eval("ProductName") %>. Чтобы в нем отображалось имя плюс текст [DISCONTINUED], при необходимости обновите декларативный синтаксис, чтобы вместо этого присвоить Text свойству значение DisplayProductNameAndDiscontinuedStatus метода . При этом необходимо передать имя продукта и неподдерживаемые значения с помощью синтаксиса Eval("columnName") . Eval возвращает значение типа Object, но DisplayProductNameAndDiscontinuedStatus метод ожидает входные параметры типа String и Boolean; поэтому необходимо привести значения, возвращаемые методом, к ожидаемым типам Eval входных параметров, например:

<h4>
    <asp:Label ID="ProductNameLabel" runat="server"
        Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
              (bool) Eval("Discontinued")) %>'>
    </asp:Label>
</h4>

Чтобы отобразить цену, можно просто присвоить UnitPriceLabel свойству Label s Text значение, возвращаемое методом DisplayPrice , так же, как и для отображения названия продукта и текста [DISCONTINUED]. Однако вместо передачи в UnitPrice качестве скалярного входного параметра мы передадим весь ProductsRow экземпляр :

<asp:Label ID="UnitPriceLabel" runat="server"
    Text='<%# DisplayPrice((Northwind.ProductsRow)
          ((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>

При вызове функций форматирования уделите некоторое время, чтобы просмотреть ход выполнения в браузере. Ваш экран должен выглядеть примерно так же, как на рис. 5, с неподдерживаемых продуктов, включая текст [DISCONTINUED] и продукты стоимостью более 20,00 долл. США с заменой на текст Пожалуйста, вызовите цену.

Снимок экрана: продукты, перечисленные в элементе управления DataList, с ценой продуктов стоимостью более 20,00 долл. США, замененными текстом

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

Сводка

Форматирование содержимого элемента управления DataList или Repeater на основе данных можно выполнить двумя способами. Первый способ — создать обработчик событий для ItemDataBound события, который срабатывает при привязке каждой записи в источнике данных к новому DataListItem объекту или RepeaterItem. В обработчике ItemDataBound событий можно проверить данные текущего элемента, а затем применить форматирование к содержимому шаблона или ко DataListItem всему элементу.

Кроме того, пользовательское форматирование можно реализовать с помощью функций форматирования. Функция форматирования — это метод, который можно вызвать из шаблонов DataList или Repeater, который возвращает HTML для выдачи на его месте. Часто HTML-код, возвращаемый функцией форматирования, определяется значениями, привязанными к текущему элементу. Эти значения можно передать в функцию форматирования в виде скалярных значений или путем передачи всего объекта, привязанного к элементу (например, экземпляру ProductsRow ).

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

Об авторе

Скотт Митчелл( Scott Mitchell), автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с веб-технологиями Майкрософт с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Sams Teach Yourself ASP.NET 2.0 в 24 часах. Он может быть доступен в mitchell@4GuysFromRolla.com. или через его блог, который можно найти по адресу http://ScottOnWriting.NET.

Особая благодарность

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