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


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

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

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

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

Введение

Как мы видели в предыдущем руководстве, DataList предлагает ряд свойств, связанных с стилем, которые влияют на его внешний вид. В частности, мы узнали, как назначить классы CSS по умолчанию свойствам DataList HeaderStyle, ItemStyle, AlternatingItemStyle и SelectedItemStyle. Помимо этих четырех свойств, DataList включает ряд других свойств, связанных со стилем, таких как Font, ForeColorBackColorи BorderWidth, чтобы назвать несколько. Элемент управления 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 вместо создания экземпляров RepeaterItem.

Замечание

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

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

Для элемента управления DataList изменения форматирования для всего элемента можно реализовать с помощью свойств, относящихся к стилю, которые включают стандартные DataListItem, Font, ForeColor, BackColor и т. д. Чтобы повлиять на форматирование определенных веб-элементов управления в шаблоне 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. Затем просмотрите DataList в браузере. Как показано на рисунке 1, единственное различие в форматировании каждого продукта заключается в том, что цвет фона альтернативный.

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

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

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

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

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

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

Protected Sub ItemDataBoundFormattingExample_ItemDataBound _
    (sender As Object, e As DataListItemEventArgs) _
    Handles ItemDataBoundFormattingExample.ItemDataBound
    If e.Item.ItemType = ListItemType.Item OrElse _
       e.Item.ItemType = ListItemType.AlternatingItem Then
        ' Programmatically reference the ProductsRow instance
        ' bound to this DataListItem
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Item.DataItem, System.Data.DataRowView).Row, _
                Northwind.ProductsRow)
        ' See if the UnitPrice is not NULL and less than $20.00
        If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
            ' TODO: Highlight the product's name and price
        End If
    End If
End Sub

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

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

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

Затем мы проверяем свойство экземпляра ProductsRowUnitPrice . Так как поле таблицы 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, которое было создано и рассмотрено в руководстве по настраиваемым форматированиям на основе данных .

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

' Highlight the product name and unit price Labels
' First, get a reference to the two Label Web controls
Dim ProductNameLabel As Label = CType(e.Item.FindControl("ProductNameLabel"), Label)
Dim UnitPriceLabel As Label = CType(e.Item.FindControl("UnitPriceLabel"), Label)
' Next, set their CssClass properties
If ProductNameLabel IsNot Nothing Then
    ProductNameLabel.CssClass = "AffordablePriceEmphasis"
End If
If UnitPriceLabel IsNot Nothing Then
    UnitPriceLabel.CssClass = "AffordablePriceEmphasis"
End If

Завершив выполнение обработчика 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 не предоставляют такие свойства уровня стиля. Поэтому применение настраиваемого форматирования к повторителу требует применения свойств стиля к веб-элементам управления в шаблонах Повторителя, как и на рис. 2.

Весь товар выделен для продуктов стоимостью менее 20 долларов США

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

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

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

Чтобы продемонстрировать функции форматирования, давайте добавим текст [ПРЕКРАЩЕНО] рядом с именем продукта, если он снят с производства. Кроме того, пусть цена выделена желтым цветом, если она меньше $ 20,00 (как мы сделали в ItemDataBound примере обработчика событий); если цена составляет $ 20,00 или выше, пусть не отображается фактическая цена, а вместо текста, пожалуйста, вызовите ценовую цитату. На рисунке 4 показан снимок экрана списка продуктов с применением этих правил форматирования.

Снимок экрана, показывающий продукты, указанные в элементе управления DataList, где цена продуктов, стоимость которых превышает $20,00, заменена текстом:

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

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

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

Protected Function DisplayProductNameAndDiscontinuedStatus _
    (productName As String, discontinued As Boolean) As String
    ' Return just the productName if discontinued is false
    If Not discontinued Then
        Return productName
    Else
        ' otherwise, return the productName appended with the text "[DISCONTINUED]"
        Return String.Concat(productName, " [DISCONTINUED]")
    End If
End Function
Protected Function DisplayPrice(product As Northwind.ProductsRow) As String
    ' If price is less than $20.00, return the price, highlighted
    If Not product.IsUnitPriceNull() AndAlso product.UnitPrice < 20 Then
        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>"
    End If
End Function

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

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

Protected Function DisplayPrice(ByVal unitPrice As Object) As String
    ' If price is less than $20.00, return the price, highlighted
    If Not Convert.IsDBNull(unitPrice) AndAlso CType(unitPrice, Decimal) < 20 Then
        Return String.Concat("<span class="AffordablePriceEmphasis">", _
            CType(unitPrice, Decimal).ToString("C"), "</span>")
    Else
        ' Otherwise return the text, "Please call for a price quote"
        Return "<span>Please call for a price quote</span>"
    End If
End Function

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

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

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

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

В элементе управления DataList ItemTemplateProductNameLabel в настоящее время отображается имя продукта, назначив его Text свойству результат<%# Eval("ProductName") %>. Чтобы отобразить имя и текст [ОТМЕНА], при необходимости обновите декларативный синтаксис, чтобы вместо этого назначить 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 значение, возвращаемое Text методом, как мы сделали для отображения имени продукта и текста [ПРЕКРАЩЕНО]. Однако, вместо передачи UnitPrice в качестве скалярного вводного параметра, мы передаем весь экземпляр ProductsRow.

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

С установленными вызовами функций форматирования потратьте немного времени, чтобы просмотреть наш прогресс в браузере. Экран должен выглядеть примерно так же, как на рис. 5, с продуктами, снятыми с производства, включая текст [ПРЕКРАЩЕНО], а у продуктов стоимостью более $ 20,00 вместо цены будет текст "Позвоните, чтобы получить ценовую информацию".

Снимок экрана, показывающий продукты, перечисленные в элементе управления DataList, цены на которые превышают $20,00 и заменены текстом

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

Сводка

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

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

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

Сведения о авторе

Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга — Sams Teach Yourself ASP.NET 2.0 за 24 часа. С ним можно связаться по адресу mitchell@4GuysFromRolla.com.

Особое спасибо кому

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