Настройка интерфейса правки элемента управления DataList (VB)

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

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

В этом руководстве мы создадим расширенный интерфейс редактирования для DataList, который включает DropDownLists и CheckBox.

Введение

Элементы управления разметкой и веб-элементы управления в элементах EditItemTemplate DataList определяют его редактируемый интерфейс. Во всех редактируемых примерах DataList, которые мы рассмотрели до сих пор, редактируемый интерфейс состоит из веб-элементов управления TextBox. В предыдущем руководстве мы улучшили взаимодействие с пользователем во время редактирования, добавив элементы управления проверкой.

Можно EditItemTemplate дополнительно развернуть, чтобы включить веб-элементы управления, отличные от TextBox, такие как DropDownLists, RadioButtonLists, Calendars и т. д. Как и в случае с TextBoxes, при настройке интерфейса редактирования для включения других веб-элементов управления выполните следующие действия.

  1. Добавьте веб-элемент управления в .EditItemTemplate
  2. Используйте синтаксис привязки данных, чтобы назначить соответствующее значение поля данных соответствующему свойству.
  3. В обработчике UpdateCommand событий программным способом получите доступ к значению веб-элемента управления и передайте его в соответствующий метод BLL.

В этом руководстве мы создадим расширенный интерфейс редактирования для DataList, который включает DropDownLists и CheckBox. В частности, мы создадим dataList, который содержит сведения о продукте и разрешает обновлять название продукта, поставщик, категорию и состояние прекращения (см. рис. 1).

Интерфейс редактирования включает TextBox, два раскрывающихся списка и CheckBox.

Рис. 1. Интерфейс редактирования включает textBox, два раскрывающихся списка и флажок (щелкните для просмотра полноразмерного изображения)

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

Прежде чем создать редактируемый интерфейс DataList, необходимо сначала создать интерфейс только для чтения. Начните с открытия CustomizedUI.aspx страницы в папке EditDeleteDataList и из Designer добавьте dataList на страницу, задав для ее ID свойства значение Products. В смарт-теге DataList создайте объект ObjectDataSource. Присвойте этому новому объекту имя ObjectDataSource ProductsDataSource и настройте его для получения данных из ProductsBLL метода класса .GetProducts Как и в предыдущих руководствах по dataList, мы обновим измененные сведения о продукте, перейдя непосредственно на уровень бизнес-логики. Соответственно, установите для раскрывающихся списков на вкладках UPDATE, INSERT и DELETE значение (Нет).

Задайте для Drop-Down Списки вкладки UPDATE, INSERT и DELETE значение (Нет)

Рис. 2. Задайте для Drop-Down Списки вкладок UPDATE, INSERT и DELETE значение (Нет) (щелкните для просмотра полноразмерного изображения)

После настройки ObjectDataSource Visual Studio создаст для DataList по умолчанию ItemTemplate имя и значение для каждого возвращаемого поля данных. Измените , ItemTemplate чтобы в шаблоне отображалось название продукта в <h4> элементе вместе с именем категории, именем поставщика, ценой и состоянием прекращения. Кроме того, добавьте кнопку Изменить, чтобы убедиться, что ее CommandName свойство имеет значение Изменить. Декларативная разметка для моего ItemTemplate приложения выглядит следующим образом:

<ItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="CategoryNameLabel" runat="server"
                    Text='<%# Eval("CategoryName") %>' />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="SupplierNameLabel" runat="server"
                    Text='<%# Eval("SupplierName") %>' />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="DiscontinuedLabel" runat="server"
                    Text='<%# Eval("Discontinued") %>' />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="EditButton"
                    Text="Edit" CommandName="Edit" />
            </td>
        </tr>
    </table>
    <br />
</ItemTemplate>

Приведенная выше разметка содержит сведения о продукте, используя <заголовок h4> для названия продукта и четыре столбца <table> для остальных полей. Классы ProductPropertyLabel и ProductPropertyValue CSS, определенные в Styles.css, обсуждались в предыдущих руководствах. На рисунке 3 показан ход выполнения при просмотре в браузере.

Отображается имя, поставщик, категория, состояние прекращения и цена каждого продукта.

Рис. 3. Отображается имя, поставщик, категория, состояние прекращения и цена каждого продукта (щелкните для просмотра полноразмерного изображения)

Шаг 2. Добавление веб-элементов управления в интерфейс редактирования

Первым шагом в создании настраиваемого интерфейса редактирования DataList является добавление необходимых веб-элементов управления в EditItemTemplate. В частности, нам нужен DropDownList для категории, другой для поставщика и CheckBox для состояния прекращения работы. Так как цена продукта в этом примере не редактируется, мы можем продолжать отображать ее с помощью веб-элемента управления Label Web.

Чтобы настроить интерфейс редактирования, щелкните ссылку Изменить шаблоны в смарт-теге DataList и выберите EditItemTemplate параметр в раскрывающемся списке. Добавьте DropDownList в и присвойте EditItemTemplate ей ID значение Categories.

Добавление раскрывающегося списка для категорий

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

Затем в смарт-теге DropDownList выберите параметр Выбрать источник данных и создайте объект ObjectDataSource с именем CategoriesDataSource. Настройте этот объект ObjectDataSource для использования CategoriesBLL метода класса GetCategories() (см. рис. 5). Затем мастер настройки источника данных DropDownList предлагает использовать поля данных для каждого ListItem свойства и TextValue . В Раскрывающемся списке отображается CategoryName поле данных и в CategoryID качестве значения используется , как показано на рисунке 6.

Создание объекта ObjectDataSource с именем CategoriesDataSource

Рис. 5. Создание объекта ObjectDataSource с именем CategoriesDataSource (щелкните для просмотра полноразмерного изображения)

Настройка полей отображения и значений в раскрывающемся списке

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

Повторите эту серию шагов, чтобы создать DropDownList для поставщиков. ID Задайте для этого DropDownList значение и присвойте Suppliers ей имя ObjectDataSource SuppliersDataSource.

После добавления двух DropDownLists добавьте CheckBox для состояния прекращения работы и TextBox для названия продукта. Задайте для ID checkBox и TextBox Discontinued значения и ProductNameсоответственно. Добавьте RequiredFieldValidator, чтобы убедиться, что пользователь предоставляет значение для названия продукта.

Наконец, добавьте кнопки Обновить и Отмена. Помните, что для этих двух кнопок крайне важно, чтобы их CommandName свойства были установлены в значения Обновить и Отмена соответственно.

Не стесняйтесь выложить интерфейс редактирования, как вам нравится. Я решил использовать тот же макет с четырьмя столбцами <table> из интерфейса только для чтения, как показано на следующем декларативном синтаксисе и снимке экрана:

<EditItemTemplate>
    <h4>
        <asp:Label ID="ProductNameLabel" runat="server"
            Text='<%# Eval("ProductName") %>' />
    </h4>
    <table border="0">
        <tr>
            <td class="ProductPropertyLabel">Name:</td>
            <td colspan="3" class="ProductPropertyValue">
                <asp:TextBox runat="server" ID="ProductName" Width="90%" />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
                    ControlToValidate="ProductName"
                    ErrorMessage="You must enter a name for the product."
                    runat="server">*</asp:RequiredFieldValidator>
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Category:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Categories" runat="server"
                    DataSourceID="CategoriesDataSource"
                    DataTextField="CategoryName" DataValueField="CategoryID" />
            </td>
            <td class="ProductPropertyLabel">Supplier:</td>
            <td class="ProductPropertyValue">
                <asp:DropDownList ID="Suppliers"
                    DataSourceID="SuppliersDataSource" DataTextField="CompanyName"
                    DataValueField="SupplierID" runat="server" />
            </td>
        </tr>
        <tr>
            <td class="ProductPropertyLabel">Discontinued:</td>
            <td class="ProductPropertyValue">
                <asp:CheckBox runat="server" id="Discontinued" />
            </td>
            <td class="ProductPropertyLabel">Price:</td>
            <td class="ProductPropertyValue">
                <asp:Label ID="UnitPriceLabel" runat="server"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
            </td>
        </tr>
        <tr>
            <td colspan="4">
                <asp:Button runat="Server" ID="UpdateButton" CommandName="Update"
                    Text="Update" />
                 
                <asp:Button runat="Server" ID="CancelButton" CommandName="Cancel"
                    Text="Cancel" CausesValidation="False" />
            </td>
        </tr>
    </table>
    <br />
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories"
        TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
        OldValuesParameterFormatString="original_{0}" SelectMethod="GetSuppliers"
        TypeName="SuppliersBLL">
    </asp:ObjectDataSource>
</EditItemTemplate>

Интерфейс редактирования расположен так же, как интерфейс Read-Only

Рис. 7. Интерфейс редактирования расположен так же, как интерфейс Read-Only (щелкните для просмотра полноразмерного изображения)

Шаг 3. Создание обработчиков событий EditCommand и CancelCommand

В настоящее время нет синтаксиса привязки данных в EditItemTemplate (за UnitPriceLabelисключением , который был скопирован в буквальном формате из ItemTemplate). Мы добавим синтаксис привязки данных на мгновение, но сначала создадим обработчики событий для событий DataList EditCommand и CancelCommand . Помните, что обработчик событий отвечает за EditCommand отрисовку CancelCommand интерфейса редактирования для элемента DataList, для которого была нажата кнопка "Изменить", в то время как задание состоит в том, чтобы вернуть DataList в состояние предварительного редактирования.

Создайте эти два обработчика событий и пусть они используют следующий код:

Protected Sub Products_EditCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.EditCommand
    ' Set the DataList's EditItemIndex property to the
    ' index of the DataListItem that was clicked
    Products.EditItemIndex = e.Item.ItemIndex
    ' Rebind the data to the DataList
    Products.DataBind()
End Sub
Protected Sub Products_CancelCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.CancelCommand
    ' Set the DataList's EditItemIndex property to -1
    Products.EditItemIndex = -1
    ' Rebind the data to the DataList
    Products.DataBind()
End Sub

При использовании этих двух обработчиков событий при нажатии кнопки Изменить отобразится интерфейс редактирования, а при нажатии кнопки Отмена отредактированный элемент возвращается в режим только для чтения. На рисунке 8 показан список данных после нажатия кнопки Изменить для Chef Anton s Gumbo Mix. Так как мы еще не добавили синтаксис привязки данных в интерфейс редактирования, ProductName элемент TextBox пуст, Discontinued флажок CheckBox снят, а первые элементы, выбранные из Categories и Suppliers DropDownLists, не добавлены.

Снимок экрана: DataList EditItemTemplate после добавления обработчиков событий EditCommand и CancelCommand и нажатия кнопки Изменить.

Рис. 8. Нажатие кнопки "Изменить" отображает интерфейс редактирования (щелкните для просмотра полноразмерного изображения)

Шаг 4. Добавление синтаксиса DataBinding в интерфейс редактирования

Чтобы в интерфейсе редактирования отображались текущие значения продукта, необходимо использовать синтаксис привязки данных для назначения значений полей данных соответствующим значениям веб-элемента управления. Синтаксис привязки данных можно применить через Designer, перейдя на экран Изменение шаблонов и выбрав ссылку Изменить dataBindings в смарт-тегах веб-элементов управления. Кроме того, синтаксис привязки данных можно добавить непосредственно в декларативную разметку.

ProductName Назначьте значение поля данных свойству ProductName TextBox sText, CategoryID значения Categories поля данных и SupplierID свойствам и Suppliers DropDownListsSelectedValue, а Discontinued значение поля данных — свойству Discontinued CheckBox sChecked. После внесения этих изменений либо через Designer, либо непосредственно через декларативную разметку, вернитесь на страницу в браузере и нажмите кнопку Изменить для Chef Anton s Gumbo Mix. Как показано на рисунке 9, синтаксис привязки данных добавил текущие значения в TextBox, DropDownLists и CheckBox.

Снимок экрана: DataList EditItemTemplate после добавления синтаксиса DataBinding и нажатия кнопки Изменить.

Рис. 9. Нажатие кнопки "Изменить" отображает интерфейс редактирования (щелкните для просмотра полноразмерного изображения)

Шаг 5. Сохранение изменений пользователя в обработчике событий UpdateCommand

Когда пользователь редактирует продукт и нажимает кнопку Обновить, происходит обратная передача и возникает событие DataList UpdateCommand . В обработчике событий необходимо считывать значения из веб-элементов управления в EditItemTemplate и интерфейсе BLL, чтобы обновить продукт в базе данных. Как мы видели в предыдущих руководствах, ProductID обновленный продукт доступен через коллекцию DataKeys . Доступ к полям, введенным пользователем, можно получить путем программной ссылки на веб-элементы управления с помощью FindControl("controlID"), как показано в следующем коде:

Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.UpdateCommand
    If Not Page.IsValid Then
        Exit Sub
    End If
    ' Read in the ProductID from the DataKeys collection
    Dim productID As Integer = Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
    ' Read in the product name and price values
    Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
    Dim categories As DropDownList=CType(e.Item.FindControl("Categories"), DropDownList)
    Dim suppliers As DropDownList = CType(e.Item.FindControl("Suppliers"), DropDownList)
    Dim discontinued As CheckBox = CType(e.Item.FindControl("Discontinued"), CheckBox)
    Dim productNameValue As String = Nothing
    If productName.Text.Trim().Length > 0 Then
        productNameValue = productName.Text.Trim()
    End If
    Dim categoryIDValue As Integer = Convert.ToInt32(categories.SelectedValue)
    Dim supplierIDValue As Integer = Convert.ToInt32(suppliers.SelectedValue)
    Dim discontinuedValue As Boolean = discontinued.Checked
    ' Call the ProductsBLL's UpdateProduct method...
    Dim productsAPI As New ProductsBLL()
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue, _
        discontinuedValue, productID)
    ' Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1
    Products.DataBind()
End Sub

Код начинается с проверки Page.IsValid свойства, чтобы убедиться, что все элементы управления проверки на странице являются допустимыми. Если Page.IsValid имеет значение True, измененное значение продукта ProductID считывается из DataKeys коллекции, а веб-элементы управления для ввода данных в объекте EditItemTemplate ссылаются программным способом. Затем значения из этих веб-элементов управления считываются в переменные, которые затем передаются в соответствующую UpdateProduct перегрузку. После обновления данных dataList возвращается в состояние предварительного редактирования.

Примечание

Я опустил логику обработки исключений, добавленную в учебнике Обработка исключений BLL- и DAL-Level , чтобы сохранить код и этот пример в фокусе. В качестве упражнения добавьте эту функцию после завершения работы с этим руководством.

Шаг 6. Обработка значений CategoryID и SupplierID со значением NULL

База данных Northwind позволяет использовать NULL значения для Products столбцов CategoryID таблицы и SupplierID . Однако наш интерфейс редактирования в настоящее время не поддерживает NULL значения. При попытке изменить продукт, имеющий NULL значение для столбцов CategoryID или SupplierID , мы получим ArgumentOutOfRangeException сообщение об ошибке, примерно следующее: "Categories" имеет значение SelectedValue, которое является недопустимым, так как оно не существует в списке элементов. Кроме того, в настоящее время нет способа изменить категорию продукта или значение поставщика с не-значенияNULL на значение, отличное NULL от значения.

Чтобы поддерживать NULL значения для категории и dropDownLists поставщика, необходимо добавить дополнительный ListItem. Я решил использовать (Нет) в Text качестве значения для этого ListItem, но вы можете изменить его на другое (например, пустую строку), если хотите. Наконец, не забудьте задать для DropDownLists AppendDataBoundItems значение True. Если вы забудете это сделать, категории и поставщики, привязанные к DropDownList, будут перезаписывать статически добавленный ListItem.

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

<asp:DropDownList ID="Categories" DataSourceID="CategoriesDataSource"
    DataTextField="CategoryName" DataValueField="CategoryID"  runat="server"
    SelectedValue='<%# Eval("CategoryID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>
...
<asp:DropDownList ID="Suppliers" DataSourceID="SuppliersDataSource"
    DataTextField="CompanyName" DataValueField="SupplierID" runat="server"
    SelectedValue='<%# Eval("SupplierID") %>' AppendDataBoundItems="True">
    <asp:ListItem Value=" Selected="True">(None)</asp:ListItem>
</asp:DropDownList>

Примечание

Статические ListItem можно добавить в Раскрывающийся список с помощью Designer или непосредственно с помощью декларативного синтаксиса. При добавлении элемента DropDownList для представления значения базы данных NULL обязательно добавьте ListItem с помощью декларативного синтаксиса. Если вы используете ListItem Редактор Collection в Designer, созданный декларативный синтаксис будет полностью пропускать Value параметр при назначении пустой строки, создавая декларативную разметку, например: <asp:ListItem>(None)</asp:ListItem>. Хотя это может выглядеть безобидно, отсутствие Value приводит к тому, что DropDownList будет использовать Text значение свойства вместо нее. Это означает, что если этот NULLListItem параметр выбран, будет предпринята попытка назначить значение (None) полю данных продукта (CategoryID или SupplierID, в этом руководстве), что приведет к исключению. При явном задании Value=""NULL значение будет присваиваться полю данных продукта при выборе NULLListItem .

Уделите немного времени, чтобы просмотреть наш прогресс в браузере. При редактировании продукта обратите внимание, что Categories и Suppliers DropDownLists имеют параметр (Нет) в начале DropDownList.

Раскрывающийся список

Рис. 10. Раскрывающийся Categories список и Suppliers включают параметр (Нет) (щелкните для просмотра полноразмерного изображения)

Чтобы сохранить параметр (None) в качестве значения базы данных NULL , необходимо вернуться к обработчику UpdateCommand событий. Измените categoryIDValue переменные и supplierIDValue так, чтобы они были целыми числами, допускаемыми значением NULL, и назначьте им значение, отличное от Nothing того, если список DropDownList SelectedValue не является пустой строкой:

Dim categoryIDValue As Nullable(Of Integer) = Nothing
If Not String.IsNullOrEmpty(categories.SelectedValue) Then
    categoryIDValue = Convert.ToInt32(categories.SelectedValue)
End If
Dim supplierIDValue As Nullable(Of Integer) = Nothing
If Not String.IsNullOrEmpty(suppliers.SelectedValue) Then
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue)
End If

При этом изменении значение будет передано Nothing в UpdateProduct метод BLL, если пользователь выбрал параметр (None) из раскрывающихся списков, который соответствует значению NULL базы данных.

Сводка

В этом руководстве мы узнали, как создать более сложный интерфейс редактирования DataList, который включал три различных входных веб-элемента управления: TextBox, два DropDownLists и CheckBox вместе с элементами управления проверки. При создании интерфейса редактирования действия выполняются одинаково независимо от используемых веб-элементов управления: начните с добавления веб-элементов управления в DataList EditItemTemplate; используйте синтаксис привязки данных для назначения соответствующих значений полей данных с соответствующими свойствами веб-элемента управления; а в UpdateCommand обработчике событий — программный доступ к веб-элементам управления и их соответствующим свойствам. передача их значений в BLL.

При создании интерфейса редактирования, состоящего только из TextBoxes или коллекции различных веб-элементов управления, не забудьте правильно обрабатывать значения базы данных NULL . При учете для NULL необходимо не только правильно отобразить существующее NULL значение в интерфейсе редактирования, но и предложить средство для пометки значения как NULL. Для DropDownLists в DataLists обычно это означает добавление статического ListItem объекта, свойство которого Value явно задано в пустую строку (Value=""), и добавление в обработчик событий немного кода UpdateCommand , чтобы определить, был ли NULL``ListItem выбран объект .

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

Об авторе

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