Использование TemplateField в элементе управления DetailsView (C#)

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

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

Те же возможности TemplateFields, доступные в GridView, также доступны в элементе управления DetailsView. В этом руководстве мы будем отображать по одному продукту за раз с помощью DetailsView, содержащего TemplateFields.

Введение

TemplateField обеспечивает более высокую степень гибкости при отрисовке данных, чем BoundField, CheckBoxField, HyperLinkField и другие элементы управления поля данных. В предыдущем руководстве мы рассмотрели использование TemplateField в GridView для выполнения следующих задач:

  • Отображение нескольких значений полей данных в одном столбце. В частности, поля FirstName и были LastName объединены в один столбец GridView.
  • Используйте альтернативный веб-элемент управления для выражения значения поля данных. Мы узнали HiredDate , как отобразить значение с помощью элемента управления Календарь.
  • Отображение сведений о состоянии на основе базовых данных. Хотя таблица Employees не содержит столбец, возвращающий количество дней, в течение которых сотрудник был на задании, мы смогли отобразить такие сведения в примере GridView в предыдущем руководстве с помощью templateField и метода форматирования.

Те же возможности TemplateFields, доступные в GridView, также доступны в элементе управления DetailsView. В этом руководстве мы будем отображать по одному продукту за раз с помощью DetailsView, содержащего два TemplateField. Первое поле TemplateField объединит UnitPriceполя данных , UnitsInStockи UnitsOnOrder в одну строку DetailsView. Второе TemplateField будет отображать значение Discontinued поля, но будет использовать метод форматирования для отображения "ДА", если Discontinued имеет значение true, и "НЕТ" в противном случае.

Для настройки отображения используются два templateField

Рис. 1. Для настройки отображения используются два поля шаблона (щелкните для просмотра полноразмерного изображения)

Приступим к работе!

Шаг 1. Привязка данных к DetailsView

Как обсуждалось в предыдущем руководстве, при работе с TemplateFields часто проще всего начать с создания элемента управления DetailsView, содержащего только BoundFields, а затем добавить новые TemplateFields или преобразовать существующие Поля BoundFields в TemplateFields при необходимости. Поэтому для начала работы с этим руководством добавьте DetailsView на страницу с помощью Designer и привязав его к ObjectDataSource, который возвращает список продуктов. Эти действия позволят создать DetailsView с BoundFields для каждого нелогического поля значения продукта и CheckBoxField для одного поля логического значения (Не поддерживается).

Откройте страницу DetailsViewTemplateField.aspx и перетащите Элемент DetailsView с панели элементов на Designer. В смарт-теге DetailsView выберите добавить новый элемент управления ObjectDataSource, который вызывает ProductsBLL метод класса GetProducts() .

Добавление нового элемента управления ObjectDataSource, который вызывает метод GetProducts()

Рис. 2. Добавление нового элемента управления ObjectDataSource, который вызывает GetProducts() метод (щелкните для просмотра полноразмерного изображения)

Для этого отчета удалите ProductID, SupplierID, CategoryIDи ReorderLevel BoundFields. Затем переупорядочение BoundFields, CategoryName чтобы и SupplierName BoundFields отображались сразу после ProductName BoundField. Вы можете настраивать HeaderText свойства и свойства форматирования для BoundFields по своему умыслу. Как и в GridView, эти изменения на уровне BoundField можно выполнять с помощью диалогового окна Поля (для доступа к ссылке Изменить поля в смарт-теге DetailsView) или декларативного синтаксиса. Наконец, очистите значения свойств DetailsView Height и Width , чтобы разрешить элементу управления DetailsView расширяться на основе отображаемых данных и проверка флажок Включить разбиение по страницам в смарт-теге.

После внесения этих изменений декларативная разметка элемента управления DetailsView должна выглядеть примерно так:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
          SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
          ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier"
          ReadOnly="True" SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
          SortExpression="UnitPrice" />
        <asp:BoundField DataField="UnitsInStock"
          HeaderText="Units In Stock" SortExpression="UnitsInStock" />
        <asp:BoundField DataField="UnitsOnOrder"
          HeaderText="Units On Order" SortExpression="UnitsOnOrder" />
        <asp:CheckBoxField DataField="Discontinued"
          HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

Просмотрите страницу в браузере. На этом этапе вы увидите один продукт в списке (Chai) со строками, показывающими название продукта, категорию, поставщика, цену, единицы на складе, единицы заказа и состояние его прекращения.

Сведения о продукте отображаются с помощью ряда BoundFields

Рис. 3. Сведения о продукте отображаются с помощью серии BoundFields (щелкните для просмотра полноразмерного изображения)

Шаг 2. Объединение цены, единиц на складе и единиц по заказу в одну строку

DetailsView содержит строку для UnitPriceполей , UnitsInStockи UnitsOnOrder . Мы можем объединить эти поля данных в одну строку с TemplateField, добавив новое TemplateField или преобразовав один из существующих UnitPriceполей , UnitsInStockи UnitsOnOrder BoundFields в TemplateField. Хотя я лично предпочитаю преобразовывать существующие BoundFields, давайте попрактиковаемся, добавив новое TemplateField.

Для начала щелкните ссылку Изменить поля в смарт-теге DetailsView, чтобы открыть диалоговое окно Поля. Затем добавьте новое templateField и задайте для его HeaderText свойства значение "Price and Inventory" (Цена и запасы) и переместите новое поле TemplateField так, чтобы оно располагалось над UnitPrice BoundField.

Добавление нового templateField в элемент управления DetailsView

Рис. 4. Добавление нового templateField в элемент управления DetailsView (щелкните для просмотра полноразмерного изображения)

Так как это новое templateField будет содержать значения, которые в настоящее время отображаются в UnitPrice, UnitsInStockи UnitsOnOrder BoundFields, давайте удалим их.

Последняя задача на этом шаге — определить разметку ItemTemplate для поля Price and Inventory TemplateField, которую можно выполнить либо с помощью интерфейса редактирования шаблона DetailsView в Designer, либо вручную с помощью декларативного синтаксиса элемента управления. Как и в случае с GridView, доступ к интерфейсу редактирования шаблона DetailsView можно получить, щелкнув ссылку Изменить шаблоны в смарт-теге. Здесь можно выбрать шаблон для редактирования из раскрывающегося списка, а затем добавить все веб-элементы управления из панели элементов.

Для работы с этим руководством начните с добавления элемента управления Метка в шаблон цены и инвентаризацииField ItemTemplate. Затем щелкните ссылку Изменить DataBindings в смарт-теге элемента управления Label Web и привяжите Text свойство к полю UnitPrice .

Привязка текстового свойства метки к полю данных UnitPrice

Рис. 5. Привязка Text свойства метки к полю UnitPrice данных (щелкните для просмотра полноразмерного изображения)

Форматирование цены в виде валюты

С этим дополнением элемент управления "Цена и инвентаризация TemplateField" теперь отображает только цену на выбранный продукт. На рисунке 6 показан снимок экрана с нашими достижениями при просмотре в браузере.

Шаблон цены и инвентаризацииВыполии показывает цену

Рис. 6. Шаблон цены и инвентаризацииВыполнение показывает цену (щелкните, чтобы просмотреть полноразмерное изображение)

Обратите внимание, что цена продукта не отформатирована как валюта. При использовании BoundField форматирование возможно путем задания свойству HtmlEncode значения false , а DataFormatString свойства — значения {0:formatSpecifier}. Однако для TemplateField все инструкции по форматированию должны быть указаны в синтаксисе привязки данных или с помощью метода форматирования, определенного в коде приложения (например, в классе кода программной части страницы ASP.NET).

Чтобы указать форматирование для синтаксиса привязки данных, используемого в элементе управления "Веб-метки", вернитесь в диалоговое окно DataBindings, щелкнув ссылку Edit DataBindings (Изменить привязки данных) из смарт-тега Label. Инструкции по форматированию можно ввести непосредственно в раскрывающемся списке Формат или выбрать одну из определенных строк формата. Как и в случае со свойством BoundField DataFormatString , форматирование задается с помощью {0:formatSpecifier}.

Для поля используйте UnitPrice форматирование валюты, указанное путем выбора соответствующего значения раскрывающегося списка или путем ввода {0:C} вручную.

Форматирование цены в виде валюты

Рис. 7. Форматирование цены в виде валюты (щелкните для просмотра полноразмерного изображения)

Декларативно спецификация форматирования указывается как второй параметр в методах Bind или Eval . Параметры, заданные с помощью Designer приводят к следующему выражению привязки данных в декларативной разметке:

<asp:Label ID="Label1" runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'/>

Добавление оставшихся полей данных в TemplateField

На этом этапе мы отображали и форматировали UnitPrice поле данных в поле Price and Inventory TemplateField, но по-прежнему UnitsInStock необходимо отобразить поля и UnitsOnOrder . Давайте отобразим их в строке под ценой и в скобках. В интерфейсе редактирования шаблона в Designer такую разметку можно добавить, разместив курсор в шаблоне и просто введя отображаемый текст. Кроме того, эту разметку можно ввести непосредственно в декларативном синтаксисе.

Добавьте статическую разметку, веб-элементы управления label и синтаксис привязки данных, чтобы в поле Price and Inventory TemplateField отображались сведения о ценах и запасах следующим образом:

UnitPrice
(На складе / в заказе:UnitsInStock / UnitsOnOrder)

После выполнения этой задачи декларативная разметка DetailsView должна выглядеть примерно так:

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
    EnableViewState="False">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="Product" SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category"
          ReadOnly="True" SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName"
          HeaderText="Supplier" ReadOnly="True"
          SortExpression="SupplierName" />
        <asp:BoundField DataField="QuantityPerUnit"
          HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
        <asp:TemplateField HeaderText="Price and Inventory">
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server"
                  Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label>
                <br />
                <strong>
                (In Stock / On Order: </strong>
                <asp:Label ID="Label2" runat="server"
                  Text='<%# Eval("UnitsInStock") %>'></asp:Label>
                <strong>/</strong>
                <asp:Label ID="Label3" runat="server"
                  Text='<%# Eval("UnitsOnOrder") %>'>
                </asp:Label><strong>)</strong>
            </ItemTemplate>
        </asp:TemplateField>
        <asp:CheckBoxField DataField="Discontinued"
           HeaderText="Discontinued" SortExpression="Discontinued" />
    </Fields>
</asp:DetailsView>

С помощью этих изменений мы объединили сведения о ценах и запасах в одну строку DetailsView.

Сведения о ценах и запасах отображаются в одной строке

Рис. 8. Сведения о ценах и запасах отображаются в одной строке (щелкните для просмотра полноразмерного изображения)

Шаг 3. Настройка сведений о неподдерживаемых полях

Столбец Products таблицы Discontinued представляет собой битовое значение, указывающее, был ли продукт прекращен. При привязке DetailsView (или GridView) к элементу управления источником данных поля логических значений, такие как Discontinued, реализуются как CheckBoxFields, тогда как поля, не являющиеся логическими значениями, такие как ProductID, ProductNameи т. д., реализуются как BoundFields. CheckBoxField отображается как отключенный флажок, который установлен, если значение поля данных равно True, в противном случае флажок снят.

Вместо того, чтобы отображать CheckBoxField, нам может потребоваться отобразить текст, указывающий, не является ли продукт прекращенным. Для этого можно удалить CheckBoxField из DetailsView, а затем добавить BoundField, свойство которого DataField имеет значение Discontinued. Уделите немного времени, чтобы сделать это. После этого изменения в DetailsView отображается текст "True" для неподдерживаемых продуктов и "False" для продуктов, которые по-прежнему активны.

Строки True и False используются для отображения состояния

Рис. 9. Строки True и False используются для отображения состояния "Неподдерживаемая" (щелкните для просмотра полноразмерного изображения)

Представьте, что мы не хотим использовать строки "True" или "False", а "ДА" и "НЕТ". Такая настройка может быть выполнена с помощью TemplateField и метода форматирования. Метод форматирования может принимать любое количество входных параметров, но должен возвращать HTML-код (в виде строки) для внедрения в шаблон.

Добавьте метод форматирования в DetailsViewTemplateField.aspx класс кода программной части страницы с именем DisplayDiscontinuedAsYESorNO , который принимает логическое значение в качестве входного параметра и возвращает строку. Как обсуждалось в предыдущем руководстве, этот метод должен быть помечен как protected или public , чтобы он был доступен из шаблона.

protected string DisplayDiscontinuedAsYESorNO(bool discontinued)
{
    if (discontinued)
        return "YES";
    else
        return "NO";
}

Этот метод проверяет входной параметр (discontinued) и возвращает значение "YES", если оно равно true, "НЕТ" в противном случае.

Примечание

В методе форматирования, рассмотренном в предыдущем руководстве, мы передавали поле данных, которое может содержать NULL и, следовательно, необходимо проверка, если значение свойства сотрудника HiredDate имеет значение базы данных NULL перед доступом к EmployeesRowсвойству HiredDate . Такой проверка здесь не требуется, так как столбцу Discontinued никогда не могут быть назначены значения базы данныхNULL. Более того, именно поэтому метод может принимать логический входной параметр вместо того, чтобы принимать ProductsRow экземпляр или параметр типа object.

После завершения этого метода форматирования остается только вызвать его из templateField ItemTemplate. Чтобы создать TemplateField, удалите Discontinued BoundField и добавьте новое templateField или преобразуйте Discontinued BoundField в TemplateField. Затем в декларативном представлении разметки измените TemplateField так, чтобы оно содержало только ItemTemplate, которое вызывает DisplayDiscontinuedAsYESorNO метод , передав значение свойства текущего ProductRow экземпляра Discontinued . Доступ к ней можно получить с помощью Eval метода . В частности, разметка TemplateField должна выглядеть следующим образом:

<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
    <ItemTemplate>
        <%# DisplayDiscontinuedAsYESorNO((bool)
          Eval("Discontinued")) %>
    </ItemTemplate>
</asp:TemplateField>

Это приведет к вызову DisplayDiscontinuedAsYESorNO метода при отрисовке DetailsView, передавая ProductRow значение экземпляра Discontinued . Eval Так как метод возвращает значение типа object, но DisplayDiscontinuedAsYESorNO метод ожидает входной параметр типа bool, мы приведение возвращаемого Eval значения методов к bool. Затем DisplayDiscontinuedAsYESorNO метод возвращает значение "YES" или "NO" в зависимости от получаемого значения. Возвращаемое значение — это то, что отображается в этой строке DetailsView (см. рис. 10).

Значения YES или NO теперь отображаются в строке

Рис. 10. Значения "ДА" или "НЕТ" отображаются в строке "Неподдерживаемые" (щелкните для просмотра полноразмерного изображения)

Сводка

TemplateField в элементе управления DetailsView обеспечивает более высокую степень гибкости при отображении данных по сравнению с другими элементами управления полями, и идеально подходит для ситуаций, когда:

  • В одном столбце GridView должно отображаться несколько полей данных
  • Данные лучше всего выражаются с помощью веб-элемента управления, а не обычного текста
  • Выходные данные зависят от базовых данных, таких как отображение метаданных или переформатирование данных

Хотя TemplateFields обеспечивают большую степень гибкости при отрисовке базовых данных DetailsView, выходные данные DetailsView по-прежнему считаются немного неровными, так как каждое поле отображается в виде строки в HTML <table>.

Элемент управления FormView обеспечивает большую степень гибкости при настройке отображаемых выходных данных. FormView не содержит поля, а просто ряд шаблонов (ItemTemplate, EditItemTemplate, HeaderTemplateи т. д.). В следующем руководстве мы рассмотрим, как использовать FormView для еще большего контроля над отображаемым макетом.

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

Об авторе

Скотт Митчелл (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.