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

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

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

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

Введение

Элементы управления Разметка и Веб в DataList EditItemTemplate определяют его редактируемый интерфейс. Во всех редактируемых примерах 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 метода класса s 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. В частности, нам нужен раскрывающийся список для категории, другой для поставщика и CheckBox для состояния прекращения работы. Так как цена продукта в этом примере не редактируется, мы можем продолжать отображать ее с помощью веб-элемента управления Label.

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

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

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

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

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

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

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

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

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

После добавления двух раскрывающихся списков добавьте Элемент 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" DataTextField="CompanyName"
                    DataSourceID="SuppliersDataSource"
                    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 void Products_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property and rebind the data
    Products.EditItemIndex = e.Item.ItemIndex;
    Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Return to DataList to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

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

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

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

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

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

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

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

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

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

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

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Make sure the page is valid...
    if (!Page.IsValid)
        return;
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    DropDownList categories = (DropDownList)e.Item.FindControl("Categories");
    DropDownList suppliers = (DropDownList)e.Item.FindControl("Suppliers");
    CheckBox discontinued = (CheckBox)e.Item.FindControl("Discontinued");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    int categoryIDValue = Convert.ToInt32(categories.SelectedValue);
    int supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);
    bool discontinuedValue = discontinued.Checked;
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, categoryIDValue, supplierIDValue,
                              discontinuedValue, productID);
    // Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1;
    Products.DataBind();
}

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

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

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

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

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

int? categoryIDValue = null;
if (!string.IsNullOrEmpty(categories.SelectedValue))
    categoryIDValue = Convert.ToInt32(categories.SelectedValue);
int? supplierIDValue = null;
if (!string.IsNullOrEmpty(suppliers.SelectedValue))
    supplierIDValue = Convert.ToInt32(suppliers.SelectedValue);

При этом изменении значение будет передано Nothing в UpdateProduct метод BLL, если пользователь выбрал параметр (Нет) из одного из раскрывающихся списков, который соответствует значению 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.