Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве мы создадим более широкий интерфейс редактирования для DataList, который включает DropDownLists и CheckBox.
Введение
Разметка и веб-элементы управления в DataList EditItemTemplate определяют его редактируемый интерфейс. Во всех редактируемых примерах DataList, которые мы изучили до сих пор, редактируемый интерфейс был состоит из веб-элементов управления TextBox. В предыдущем руководстве мы улучшили взаимодействие с пользователем во время редактирования, добавив элементы управления проверкой.
Его EditItemTemplate можно дополнительно расширить, чтобы включить веб-элементы управления, отличные от TextBox, такие как DropDownLists, RadioButtonLists, Calendars и т. д. Как и в TextBoxes, при настройке интерфейса редактирования для включения других веб-элементов управления выполните следующие действия.
- Добавьте элемент управления Web в
EditItemTemplate. - Используйте синтаксис привязки данных, чтобы назначить соответствующее значение поля данных соответствующему свойству.
- В обработчике
UpdateCommandсобытий программным образом обращается к значению веб-элемента управления и передает его в соответствующий метод BLL.
В этом руководстве мы создадим более широкий интерфейс редактирования для DataList, который включает DropDownLists и CheckBox. В частности, мы создадим DataList, который содержит сведения о продукте и разрешает обновлять имя продукта, поставщик, категорию и прекращенное состояние (см. рис. 1).
Рис. 1. Интерфейс редактирования включает текстовое поле, два раскрывающихся списка и флажок (щелкните, чтобы просмотреть изображение полного размера)
Шаг 1. Отображение сведений о продукте
Прежде чем создать редактируемый интерфейс DataList, сначала необходимо создать интерфейс только для чтения. Начните с открытия страницы CustomizedUI.aspx из папки EditDeleteDataList, затем в конструкторе добавьте на эту страницу элемент DataList, установив его свойство ID в Products. Создайте объект ObjectDataSource из смарт-тега DataList. Присвойте имя этому новому ObjectDataSource ProductsDataSource и настройте его для получения данных из класса ProductsBLL метода GetProducts. Как и в предыдущих руководствах по редактированию DataList, мы обновим измененные сведения о продукте, перейдя непосредственно на уровень бизнес-логики. Соответственно, установите раскрывающиеся списки на вкладках UPDATE, INSERT и DELETE в положение (Нет).
Рис. 2. Установите вкладки UPDATE, INSERT и DELETE списков Drop-Down на (Ничего) (Щелкните, чтобы просмотреть изображение полного размера)
После настройки ObjectDataSource Visual Studio создаст значение по умолчанию ItemTemplate для DataList, который содержит имя и значение для каждого возвращаемого поля данных.
ItemTemplate Измените шаблон таким образом, чтобы шаблон перечислял имя продукта в <h4> элементе вместе с именем категории, именем поставщика, ценой и прекращенным состоянием. Кроме того, добавьте кнопку "Изменить", убедившись, что его CommandName свойство имеет значение Edit. Декларативная разметка для моего 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. В частности, нам нужен выпадающий список для категории, другой для поставщика, а также флажок для состояния прекращения. Так как цена продукта не редактируется в этом примере, мы можем продолжать отображать его с помощью веб-элемента управления Label.
Чтобы настроить интерфейс редактирования, щелкните ссылку "Изменить шаблоны" из смарт-тега DataList и выберите EditItemTemplate вариант из раскрывающегося списка. Добавьте выпадающий список в EditItemTemplate и установите его ID на Categories.
Рис. 4. Добавление раскрывающегося списка для категорий (щелкните, чтобы просмотреть изображение полного размера)
Затем в смарт-теге DropDownList выберите параметр "Выбрать источник данных" и создайте новый объект ObjectDataSource с именем CategoriesDataSource. Настройте этот объект ObjectDataSource для использования CategoriesBLL метода класса GetCategories() (см. рис. 5). Затем Мастер настройки источника данных DropDownList запрашивает поля данных, которые будут использоваться для каждого ListItem из Text них и Value свойств. В раскрывающемся списке отображается поле данных CategoryName, а в качестве значения используется CategoryID, как показано на рис. 6.
Рис. 5. Создание объекта ObjectDataSource С именем CategoriesDataSource (щелкните, чтобы просмотреть изображение полного размера)
Рис. 6. Настройка полей отображения и значения dropDownList (щелкните, чтобы просмотреть изображение полного размера)
Повторите эту последовательность шагов, чтобы создать выпадающий список (DropDownList) для поставщиков. Установите ID для этого элемента DropDownList в Suppliers и назовите его ObjectDataSource SuppliersDataSource.
После добавления двух списков DropDownList, добавьте флажок для статуса прекращения и текстовое поле для имени продукта. Установите для CheckBox значение ID, а для TextBox — значение Discontinued и ProductName соответственно. Добавьте RequiredFieldValidator, чтобы убедиться, что пользователь предоставляет значение имени продукта.
Наконец, добавьте кнопки "Обновить" и "Отмена". Помните, что для этих двух кнопок крайне важно, чтобы их CommandName свойства были заданы как Update и Cancel соответственно.
Вы можете настроить интерфейс редактирования так, как вам удобно. Я решил использовать тот же макет четырех столбцов <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>
Рис. 7. Интерфейс редактирования выложен, как интерфейс Read-Only (щелкните, чтобы просмотреть изображение полного размера)
Шаг 3. Создание обработчиков событий EditCommand и CancelCommand
В настоящее время в синтаксисе EditItemTemplate отсутствует привязка данных (за исключением синтаксиса UnitPriceLabel, который был скопирован дословно из ItemTemplate). Мы добавим синтаксис привязки данных мгновенно, но сначала создадим обработчики событий для dataList EditCommand и CancelCommand событий. Помните, что EditCommand обработчик событий отвечает за отображение интерфейса редактирования для элемента DataList, кнопку редактирования которого нажали, в то время как задача CancelCommand состоит в возвращении 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 показан DataList после нажатия кнопки "Изменить" для Chef Anton's Gumbo Mix. Так как мы еще не добавили никакого синтаксиса привязки данных в интерфейс редактирования, ProductName TextBox пустой, Discontinued флажок снят, и первые элементы выбраны в раскрывающихся списках Categories и Suppliers.
Рис. 8. Нажатие кнопки "Изменить" отображает интерфейс редактирования (щелкните, чтобы просмотреть изображение полного размера)
Шаг 4. Добавление синтаксиса DataBinding в интерфейс редактирования
Чтобы интерфейс редактирования отображал текущие значения продукта, необходимо использовать синтаксис привязки данных для назначения значений поля данных соответствующим значениям веб-элемента управления. Синтаксис привязки данных можно применить с помощью конструктора, перейдя на экран "Изменить шаблоны" и выбрав ссылку "Изменить привязки данных" из смарт-тегов веб-элементов управления. Кроме того, синтаксис привязки данных можно добавить непосредственно в декларативную разметку.
Назначьте значение поля данных ProductName свойству ProductName TextBox, значения полей данных CategoryID и SupplierID свойствам Categories и Suppliers DropDownLists, и значение поля данных Discontinued свойству Discontinued CheckBox. После внесения этих изменений с помощью конструктора или непосредственно через декларативную разметку, просмотрите страницу через браузер и нажмите кнопку «Изменить» для продукта "Chef Anton's Gumbo Mix". Как показано на рисунке 9, синтаксис привязки данных добавил текущие значения в TextBox, DropDownLists и CheckBox.
Рис. 9. Нажатие кнопки "Изменить" отображает интерфейс редактирования (щелкните, чтобы просмотреть изображение полного размера)
Шаг 5. Сохранение изменений пользователя в обработчике событий UpdateCommand
Когда пользователь редактирует продукт и нажимает кнопку "Обновить", происходит постбэк, и событие DataList UpdateCommand запускается. В обработчике событий необходимо считывать значения из веб-элементов управления в EditItemTemplate и взаимодействовать с уровнем бизнес-логики (BLL), чтобы обновить продукт в базе данных. Как мы видели в предыдущих учебниках, доступ к этому обновленному продукту осуществляется через коллекцию 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. Обработка значений NULL CategoryID и SupplierID
База данных Northwind позволяет использовать NULL значения для Products таблиц CategoryID и SupplierID столбцов. Однако наш интерфейс редактирования в настоящее время не поддерживает значения NULL. Если мы пытаемся изменить продукт, у которого значение в столбцах NULL или CategoryID, мы получим SupplierID сообщение об ошибке, аналогичное следующему: ArgumentOutOfRangeException Также в настоящее время нет возможности изменить категорию продукта или значение поставщика с значения, отличного от , на значение NULL.
Чтобы поддерживать значения NULL для списков "категория" и "поставщик" в DropDownLists, необходимо добавить дополнительный элемент ListItem. Я выбрал использовать (None) в качестве Text значения для этого ListItem, но вы можете изменить его на что-то другое (например, пустую строку), если вы хотите. Наконец, не забудьте задать значение DropDownLists AppendDataBoundItemsTrue; если вы забыли сделать это, категории и поставщики, привязанные к 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 s можно добавлять в DropDownList через дизайнер или напрямую через декларативный синтаксис. При добавлении элемента DropDownList для представления значения базы данных NULL, убедитесь, что добавили его ListItem с помощью декларативного синтаксиса. Если вы используете ListItem редактор коллекции в конструкторе, созданный декларативный синтаксис полностью опустит Value параметр при назначении пустой строки, создав декларативную разметку, например: <asp:ListItem>(None)</asp:ListItem> Хотя это может выглядеть безвредно, отсутствие Value вызывает DropDownList использовать значение свойства Text на своем месте. Это означает, что при выборе NULLListItem будет сделана попытка назначить значение (None) полю данных продукта (CategoryID или SupplierID, как упомянуто в этом руководстве), что приведет к исключению. Явно задайте Value="", чтобы значение NULL было назначено полю данных продукта при выборе NULLListItem.
Ознакомьтесь с нашим прогрессом в браузере. При редактировании продукта обратите внимание, что Categories и Suppliers DropDownLists имеют параметр (None) в начале раскрывающегося списка.
Рис. 10. В Categories раскрывающемся Suppliers списке включен параметр (Нет) (щелкните, чтобы просмотреть изображение полного размера)
Чтобы сохранить параметр (None) в качестве значения базы данных NULL , необходимо вернуться в UpdateCommand обработчик событий. Измените переменные categoryIDValue и supplierIDValue на целые числа, допускающие значение NULL, и назначьте им значение, отличное от Nothing, только если значение выпадающего списка 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, если пользователь выбрал параметр (None) из раскрывающихся списков, соответствующий NULL значению базы данных.
Итоги
В этом руководстве мы узнали, как создать более сложный интерфейс редактирования DataList, который включал три различных веб-элемента управления: текстовое поле, два выпадающих списка и флажок, а также элементы управления для проверки. При создании интерфейса редактирования шаги одинаковы независимо от используемых веб-элементов управления: начните с добавления веб-элементов управления в DataList EditItemTemplate; используйте синтаксис привязки данных для назначения соответствующих значений полей данных с соответствующими свойствами веб-элемента управления; и UpdateCommand в обработчике событий программным образом обращается к веб-элементам управления и их соответствующим свойствам. передает значения в BLL.
При создании интерфейса редактирования, независимо от того, состоит ли он только из TextBoxes или коллекции различных веб-элементов управления, обязательно правильно обрабатывайте значения базы данных NULL . При учете NULL s необходимо не только правильно отображать существующее значение NULL в интерфейсе редактирования, но и предлагать средства для пометки значения как NULL. Для DropDownLists в DataLists это обычно означает добавление статического элемента ListItem, свойство которого Value явно установлено в пустую строку (Value=""), и добавление немного кода в обработчик событий UpdateCommand, чтобы определить, был ли выбран NULL``ListItem.
Счастливое программирование!
Об авторе
Скотт Митчелл, автор семи книг ASP/ASP.NET и основатель 4GuysFromRolla.com, работает с технологиями Microsoft Web с 1998 года. Скотт работает независимым консультантом, тренером и писателем. Его последняя книга Самоучитель Sams по ASP.NET 2.0 за 24 часа. Его можно достичь по адресу mitchell@4GuysFromRolla.com.
Особое спасибо кому
Эта серия учебников была проверена многими полезными рецензентами. Ведущие рецензенты этого руководства: Деннис Паттерсон, Дэвид Суру и Рэнди Шмидт. Хотите просмотреть мои предстоящие статьи MSDN? Если да, напишите мне на mitchell@4GuysFromRolla.com.