自定义 DataList 的编辑界面 (VB)
在本教程中,我们将为 DataList 创建更丰富的编辑界面,其中包括 DropDownLists 和 CheckBox。
简介
DataList 中的 EditItemTemplate
标记和 Web 控件定义其可编辑接口。 在我们到目前为止检查的所有可编辑 DataList 示例中,可编辑的界面都由 TextBox Web 控件组成。 在 前面的教程中 ,我们通过添加验证控件改进了编辑时用户体验。
EditItemTemplate
可以进一步扩展,以包含除 TextBox 以外的 Web 控件,例如 DropDownLists、RadioButtonLists、Calendars 等。 与 TextBoxs 一样,在自定义编辑界面以包含其他 Web 控件时,请使用以下步骤:
- 将 Web 控件添加到
EditItemTemplate
。 - 使用数据绑定语法将相应的数据字段值分配给相应的属性。
- 在事件处理程序中
UpdateCommand
,以编程方式访问 Web 控件值,并将其传递到相应的 BLL 方法中。
在本教程中,我们将为 DataList 创建更丰富的编辑界面,其中包括 DropDownLists 和 CheckBox。 具体而言,我们将创建一个 DataList,用于列出产品信息,并允许更新产品名称、供应商、类别和停产状态, (请参阅图 1) 。
图 1:编辑界面包括一个 TextBox、两个 DropDownList 和一个 CheckBox (单击以查看全尺寸图像)
步骤 1:显示产品信息
在创建 DataList 的可编辑接口之前,首先需要生成只读接口。 首先从 文件夹中打开CustomizedUI.aspx
页面,然后从 Designer向页面添加 DataList,并将其ID
属性设置为 Products
。EditDeleteDataList
在 DataList 的智能标记中,创建新的 ObjectDataSource。 将此新的 ObjectDataSource ProductsDataSource
命名为 ,并将其配置为从 ProductsBLL
类 s GetProducts
方法检索数据。 与前面的可编辑 DataList 教程一样,我们将通过直接转到业务逻辑层来更新已编辑的产品信息。 相应地,将“更新”、“插入”和“删除”选项卡中的下拉列表设置为“无”) (。
图 2:将“更新”、“插入”和“删除”选项卡 Drop-Down Lists 设置为“无 () (单击以查看全尺寸图像)
配置 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
在 中Styles.css
定义的 和 ProductPropertyValue
CSS 类已在前面的教程中进行了讨论。 图 3 显示了通过浏览器查看时的进度。
图 3:显示每个产品的名称、供应商、类别、停产状态和价格 (单击以查看全尺寸图像)
步骤 2:将 Web 控件添加到编辑界面
生成自定义 DataList 编辑界面的第一步是将所需的 Web 控件添加到 EditItemTemplate
。 具体而言,我们需要一个 DropDownList 作为类别,另一个用于供应商,一个 CheckBox 用于停产状态。 由于在此示例中,产品价格不可编辑,因此我们可以使用标签 Web 控件继续显示它。
若要自定义编辑界面,请单击 DataList 智能标记中的“编辑模板”链接, EditItemTemplate
然后从下拉列表中选择选项。 将 DropDownList 添加到 ,EditItemTemplate
并将其ID
Categories
设置为 。
图 4:为“类别”添加 DropDownList (单击以查看全尺寸图像)
接下来,从 DropDownList 的智能标记中选择“选择数据源”选项,并创建名为 CategoriesDataSource
的新 ObjectDataSource。 配置此 ObjectDataSource 以使用 CategoriesBLL
类方法 GetCategories()
(请参阅图 5) 。 接下来,DropDownList 的数据源配置向导会提示输入要用于每个 ListItem
s 和Value
属性的数据Text
字段。 让 DropDownList 显示 CategoryName
数据字段并使用 CategoryID
作为值,如图 6 所示。
图 5:新建名为 CategoriesDataSource
的对象数据源 (单击以查看全尺寸图像)
图 6:配置 DropDownList 的显示字段和值字段 (单击以查看全尺寸图像)
重复这一系列步骤,为供应商创建 DropDownList。 ID
将此 DropDownList 的 设置为 Suppliers
,并将其命名为 ObjectDataSource SuppliersDataSource
。
添加两个 DropDownList 后,为停产状态添加 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>
图 7:编辑界面的布局类似于 Read-Only 界面 (单击以查看全尺寸图像)
步骤 3:创建 EditCommand 和 CancelCommand 事件处理程序
目前,除了 从 ItemTemplate
) UnitPriceLabel
逐字复制的 , (中没有数据绑定语法EditItemTemplate
。 我们将暂时添加数据绑定语法,但首先让我们为 DataList EditCommand
和 CancelCommand
事件创建事件处理程序。 回想一下,事件处理程序的责任 EditCommand
是呈现单击了“编辑”按钮的 DataList 项的编辑界面,而 CancelCommand
s 作业是将 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 的 Gumbo Mix 的“编辑”按钮后的数据列表。 由于我们尚未向编辑界面添加任何数据绑定语法, ProductName
TextBox 为空, Discontinued
CheckBox 处于未选中状态,并且从 Categories
和 Suppliers
DropDownLists 中选择的第一个项。
图 8:单击“编辑”按钮显示编辑界面 (单击以查看全尺寸图像)
步骤 4:向编辑接口添加数据绑定语法
若要使编辑界面显示当前产品的 值,我们需要使用数据绑定语法将数据字段值分配给相应的 Web 控件值。 可以通过Designer应用数据绑定语法,方法是转到“编辑模板”屏幕,然后从 Web 控件智能标记中选择“编辑数据绑定”链接。 或者,可以将数据绑定语法直接添加到声明性标记。
将数据 ProductName
字段值分配给 ProductName
TextBox 属性 Text
,将 CategoryID
和 SupplierID
数据字段值分配给 Categories
和 Suppliers
DropDownLists SelectedValue
属性,并将 Discontinued
数据字段值分配给 Discontinued
CheckBox 的 Checked
属性。 进行这些更改后,无论是通过Designer还是直接通过声明性标记,通过浏览器重新访问页面,然后单击 Chef Anton s Gumbo Mix 的“编辑”按钮。 如图 9 所示,数据绑定语法已将当前值添加到 TextBox、DropDownLists 和 CheckBox 中。
图 9:单击“编辑”按钮显示编辑界面 (单击以查看全尺寸图像)
步骤 5:在 UpdateCommand 事件处理程序中保存用户更改
当用户编辑产品并单击“更新”按钮时,会发生回发,并触发 DataList 事件 UpdateCommand
。 在事件处理程序中,我们需要从 和 与 BLL 接口的 EditItemTemplate
Web 控件中读取值,以更新数据库中的产品。 正如我们在前面的教程中看到的那样, ProductID
可通过 集合访问 DataKeys
更新产品的 。 通过使用 以编程方式引用 Web 控件 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
,则从DataKeys
集合中读取已编辑的产品ProductID
值,并且以编程方式引用 中的数据EditItemTemplate
条目 Web 控件。 接下来,将这些 Web 控件中的值读取到变量中,然后传递到相应的 UpdateProduct
重载。 更新数据后,DataList 将返回到其预编辑状态。
注意
为了保持代码和此示例的焦点,我省略了 在处理 BLL 和 DAL-Level 异常 教程中添加的异常处理逻辑。 作为练习,请在完成本教程后添加此功能。
步骤 6:处理 NULL CategoryID 和 SupplierID 值
Northwind 数据库允许NULL
表和CategoryID
SupplierID
列的值Products
。 但是,我们的编辑界面当前无法容纳 NULL
值。 如果我们尝试编辑具有其 或 列的值的产品NULL
,我们将得到一个ArgumentOutOfRangeException
,其中包含类似于:“Categories”的 SelectedValue,因为它不存在于项列表中。SupplierID
CategoryID
此外,目前无法将产品类别或供应商价值从非NULL
值更改为NULL
非值。
若要支持 NULL
类别和供应商 DropDownLists 的值,我们需要添加其他 ListItem
。 我已选择使用 (None) 作为 Text
此值 ListItem
,但你可以根据需要将其更改为其他 (,例如空字符串) 。 最后,请记住将 DropDownList 设置为 AppendDataBoundItems
True
;如果忘记这样做,绑定到 DropDownList 的类别和供应商将覆盖静态添加 ListItem
的 。
进行这些更改后,DataList 中的 EditItemTemplate
DropDownLists 标记应如下所示:
<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。 添加 DropDownList 项以表示数据库 NULL
值时,请务必通过声明性语法添加 ListItem
。 如果在Designer中使用ListItem
集合编辑器,则当分配空字符串时,生成的声明性语法将完全省略Value
该设置,从而创建声明性标记,如:<asp:ListItem>(None)</asp:ListItem>
。 虽然这看起来可能无害,但缺失 Value
会导致 DropDownList 在其位置使用 Text
属性值。 这意味着,如果 NULL
ListItem
选择此选项,则将尝试将值 (None) 分配给产品数据字段 (CategoryID
或 SupplierID
,在本教程) ,这将导致异常。 通过显式设置 Value=""
,当选择 时NULL
ListItem
,将向产品数据字段分配一个NULL
值。
花点时间通过浏览器查看进度。 编辑产品时,请注意 Categories
,和 Suppliers
DropDownLists 在 DropDownList 的开头都有一个“ (无) ”选项。
图 10:和 Categories
Suppliers
DropDownLists 包括“无 (”) 选项 (单击以查看全尺寸图像)
若要将“ (无) ”选项保存为数据库 NULL
值,需要返回到 UpdateCommand
事件处理程序。 将 categoryIDValue
和 supplierIDValue
变量更改为可以为 null 的整数,并仅当 DropDownList s SelectedValue
不是空字符串时为其赋值Nothing
:
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
下拉列表中选择了“无) (”选项(对应于NULL
数据库值),则会将 UpdateProduct
值传递到 BLL 方法中。
总结
在本教程中,我们了解了如何创建更复杂的 DataList 编辑界面,该界面包括三个不同的输入 Web 控件一个 TextBox、两个 DropDownList 和一个 CheckBox 以及验证控件。 生成编辑界面时,无论使用何种 Web 控件,步骤都是相同的:首先将 Web 控件添加到 DataList; EditItemTemplate
使用数据绑定语法为相应的数据字段值分配相应的 Web 控件属性;并在事件处理程序中 UpdateCommand
以编程方式访问 Web 控件及其相应属性, 将其值传递到 BLL。
创建编辑界面时,无论它只由 TextBox 或不同 Web 控件的集合组成,请务必正确处理数据库 NULL
值。 在考虑 NULL
时,必须不仅在编辑界面中正确显示现有 NULL
值,而且必须提供一种将值标记为 NULL
的方法。 对于 DataLists 中的 DropDownLists,这通常意味着添加一个静态 ListItem
,其 Value
属性显式设置为空字符串 (Value=""
) ,并将一些代码添加到 UpdateCommand
事件处理程序,以确定是否 NULL``ListItem
选择了 。
编程快乐!
关于作者
斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。
特别感谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是丹尼斯·帕特森、大卫·苏鲁和兰迪·施密特。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处mitchell@4GuysFromRolla.com放置一行。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈