在 DataList (C#) 中编辑和删除数据概述
虽然 DataList 缺乏内置的编辑和删除功能,但本教程将介绍如何创建支持编辑和删除其基础数据的 DataList。
简介
在 插入、更新和删除数据概述 教程中,我们介绍了如何使用应用程序体系结构、ObjectDataSource 以及 GridView、DetailsView 和 FormView 控件插入、更新和删除数据。 使用 ObjectDataSource 和这三个数据 Web 控件时,实现简单的数据修改接口是一个快照,只需勾选智能标记中的复选框即可。 无需编写代码。
遗憾的是,DataList 缺少 GridView 控件中固有的内置编辑和删除功能。 缺少此功能的部分原因在于,当声明性数据源控件和无代码数据修改页不可用时,DataList 是以前版本的 ASP.NET 的遗物。 虽然 ASP.NET 2.0 中的 DataList 不提供与 GridView 相同的现成数据修改功能,但我们可以使用 ASP.NET 1.x 技术来包含此类功能。 此方法需要一些代码,但正如本教程中所示,DataList 提供了一些事件和属性来帮助完成此过程。
本教程介绍如何创建支持编辑和删除其基础数据的 DataList。 未来的教程将介绍更高级的编辑和删除方案,包括输入字段验证、正常处理从数据访问层或业务逻辑层引发的异常等。
注意
与 DataList 一样,Repeater 控件缺少用于插入、更新或删除的现成功能。 虽然可以添加此类功能,但 DataList 包括中继器中找不到的属性和事件,这些属性和事件可简化此类功能的添加。 因此,本教程和将来查看编辑和删除的内容将严格关注 DataList。
步骤 1:创建编辑和删除教程网页
在开始探索如何更新和删除 DataList 中的数据之前,让我们先花点时间在网站项目中创建本教程和后续几个页面所需的 ASP.NET 页面。 首先添加名为 EditDeleteDataList
的新文件夹。 接下来,将以下 ASP.NET 页添加到该文件夹,确保将每个页面与 Site.master
母版页相关联:
Default.aspx
Basics.aspx
BatchUpdate.aspx
ErrorHandling.aspx
UIValidation.aspx
CustomizedUI.aspx
OptimisticConcurrency.aspx
ConfirmationOnDelete.aspx
UserLevelAccess.aspx
图 1:为教程添加 ASP.NET 页
与其他文件夹中一样, Default.aspx
在 EditDeleteDataList
文件夹中列出了其部分中的教程。 回想一下, SectionLevelTutorialListing.ascx
用户控件提供此功能。 因此,将此用户控件Default.aspx
从解决方案资源管理器拖到页面设计视图中,将其添加到 。
图 2:将 SectionLevelTutorialListing.ascx
用户控件添加到 Default.aspx
(单击以查看全尺寸图像)
最后,将页面作为条目添加到文件中 Web.sitemap
。 具体而言,使用 DataList 和 Repeater <siteMapNode>
在 Master/Detail Reports 后面添加以下标记:
<siteMapNode
title="Editing and Deleting with the DataList"
description="Samples of Reports that Provide Editing and Deleting Capabilities"
url="~/EditDeleteDataList/Default.aspx" >
<siteMapNode
title="Basics"
description="Examines the basics of editing and deleting with the
DataList control."
url="~/EditDeleteDataList/Basics.aspx" />
<siteMapNode
title="Batch Update"
description="Examines how to update multiple records at once in a
fully-editable DataList."
url="~/EditDeleteDataList/BatchUpdate.aspx" />
<siteMapNode
title="Error Handling"
description="Learn how to gracefully handle exceptions raised during the
data modification workflow."
url="~/EditDeleteDataList/ErrorHandling.aspx" />
<siteMapNode
title="Adding Data Entry Validation"
description="Help prevent data entry errors by providing validation."
url="~/EditDeleteDataList/UIValidation.aspx" />
<siteMapNode
title="Customize the User Interface"
description="Customize the editing user interfaces."
url="~/EditDeleteDataList/CustomizedUI.aspx" />
<siteMapNode
title="Optimistic Concurrency"
description="Learn how to help prevent simultaneous users from
overwritting one another s changes."
url="~/EditDeleteDataList/OptimisticConcurrency.aspx" />
<siteMapNode
title="Confirm On Delete"
description="Prompt a user for confirmation when deleting a record."
url="~/EditDeleteDataList/ConfirmationOnDelete.aspx" />
<siteMapNode
title="Limit Capabilities Based on User"
description="Learn how to limit the data modification functionality
based on the user s role or permissions."
url="~/EditDeleteDataList/UserLevelAccess.aspx" />
</siteMapNode>
更新 Web.sitemap
后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包含 DataList 编辑和删除教程的项。
图 3:站点地图现在包含 DataList 编辑和删除教程的条目
步骤 2:检查更新和删除数据的技术
使用 GridView 编辑和删除数据非常简单,因为 GridView 和 ObjectDataSource 在封面下协同工作。 如 检查与插入、更新和删除关联的事件 教程中所述,单击行的“更新”按钮时,GridView 会自动将其使用双向数据绑定的 UpdateParameters
字段分配给其 ObjectDataSource 的集合,然后调用该 ObjectDataSource 方法 Update()
。
可悲的是,DataList 不提供任何此类内置功能。 我们有责任确保将用户的值分配给 ObjectDataSource 的参数,并调用其 Update()
方法。 为了帮助我们完成此工作,DataList 提供了以下属性和事件:
- 更新
DataKeyField
或删除 属性时,我们需要能够唯一标识 DataList 中的每个项。 将此属性设置为所显示数据的主键字段。 这样做将使用每个 DataList 项的指定值填充 DataList 集合DataKeys
。DataKeyField
- 单击
EditCommand
属性设置为“编辑”的CommandName
Button、LinkButton 或 ImageButton 时,将触发事件。 - 单击
CancelCommand
属性设置为“取消”的CommandName
Button、LinkButton 或 ImageButton 时,将触发事件。 - 单击
UpdateCommand
属性设置为“更新”的CommandName
Button、LinkButton 或 ImageButton 时,将触发事件。 - 单击
DeleteCommand
属性设置为“删除”的CommandName
Button、LinkButton 或 ImageButton 时,将触发事件。
使用这些属性和事件,可以使用四种方法来更新和删除 DataList 中的数据:
- 使用 ASP.NET 1.x 技术 ,DataList 存在于 ASP.NET 2.0 和 ObjectDataSources 之前,并且能够通过编程方式完全更新和删除数据。 此方法完全放弃 ObjectDataSource,并要求我们直接从业务逻辑层将数据绑定到 DataList,无论是检索要显示的数据,还是在更新或删除记录时。
- 在页面上使用单个 ObjectDataSource 控件进行选择、更新和删除, 而 DataList 缺少 GridView 固有的编辑和删除功能,我们没有理由不能自行添加它们。 使用此方法时,我们使用 ObjectDataSource,就像 GridView 示例中一样,但必须为 DataList 事件
UpdateCommand
创建事件处理程序,在该事件中设置 ObjectDataSource 的参数并调用其Update()
方法。 - 使用 ObjectDataSource 控件进行选择,但在使用选项 2 时直接针对 BLL 进行更新和删除 ,我们需要在 事件中
UpdateCommand
编写一些代码,分配参数值等。 相反,我们可以坚持使用 ObjectDataSource 进行选择,但直接对 BLL (进行更新和删除调用,如使用选项 1) 。 在我看来,通过与 BLL 直接交互来更新数据比分配 ObjectDataSourceUpdateParameters
并调用其Update()
方法更易读的代码。 - 通过 Multiple ObjectDataSources 使用声明性手段 ,前三种方法都需要一些代码。 如果希望尽可能多地使用声明性语法,最后一个选项是在页面上包含多个 ObjectDataSource。 第一个 ObjectDataSource 从 BLL 检索数据并将其绑定到 DataList。 为了进行更新,添加了另一个 ObjectDataSource,但直接在 DataList 的 中添加
EditItemTemplate
。 若要包含删除支持,还需要在 中ItemTemplate
另一个 ObjectDataSource。 使用此方法,这些嵌入的 ObjectDataSource 用于ControlParameters
以声明方式将 ObjectDataSource 的参数绑定到用户输入控件 (,而无需在 DataList 的UpdateCommand
事件处理程序) 中以编程方式指定它们。 此方法仍需要一些代码,我们需要调用嵌入的 ObjectDataSource 或Update()
Delete()
命令,但所需的代码远远低于其他三种方法。 此处的缺点是,多个 ObjectDataSources 使页面变得混乱,损害了整体可读性。
如果强制只使用其中一种方法,我会选择选项 1,因为它提供了最大的灵活性,并且 DataList 最初设计用于适应此模式。 虽然 DataList 已扩展为与 ASP.NET 2.0 数据源控件配合使用,但它没有 GridView、DetailsView 和 FormView) (官方 ASP.NET 2.0 数据 Web 控件的所有扩展点或功能。 不过,选项 2 到 4 并非没有优点。
本和将来的编辑和删除教程将使用 ObjectDataSource 检索要显示的数据,并直接调用 BLL 以更新和删除 (选项 3) 的数据。
步骤 3:添加 DataList 并配置其 ObjectDataSource
在本教程中,我们将创建一个列出产品信息的 DataList,并针对每个产品为用户提供编辑名称和价格以及完全删除产品的功能。 具体而言,我们将使用 ObjectDataSource 检索要显示的记录,但通过与 BLL 直接交互来执行更新和删除操作。 在担心对 DataList 实现编辑和删除功能之前,让我们先获取页面,以在只读界面中显示产品。 由于我们在前面的教程中检查了这些步骤,因此我将快速完成这些步骤。
首先打开 文件夹中的页面Basics.aspx
EditDeleteDataList
,然后从“设计”视图向页面添加 DataList。 接下来,从 DataList 的智能标记中创建新的 ObjectDataSource。 由于我们正在处理产品数据,因此请将其配置为使用 ProductsBLL
类。 若要检索 所有 产品,请在 GetProducts()
SELECT 选项卡中选择 方法。
图 4:将 ObjectDataSource 配置为使用 ProductsBLL
类 (单击以查看全尺寸图像)
图 5:使用 GetProducts()
方法返回产品信息 (单击以查看全尺寸图像)
DataList(与 GridView 一样)不是用于插入新数据的设计。因此,请从“插入”选项卡的下拉列表中选择“ (无) ”选项。此外,为“更新”和“删除”选项卡选择“ (”无“) ,因为更新和删除将通过 BLL 以编程方式执行。
图 6:确认 ObjectDataSource 的 INSERT、UPDATE 和 DELETE 选项卡中的 Drop-Down Lists 设置为“无 (”) (单击以查看全尺寸图像)
配置 ObjectDataSource 后,单击“完成”,返回到Designer。 正如我们在过去示例中所看到的,完成 ObjectDataSource 配置时,Visual Studio 会自动为 DropDownList 创建 , ItemTemplate
并显示每个数据字段。 将此 ItemTemplate
替换为仅显示产品名称和价格的 。 此外,将 RepeatColumns
属性设置为 2。
注意
如 插入、更新和删除数据概述 教程中所述,使用 ObjectDataSource 修改数据时,体系结构要求从 ObjectDataSource 声明性标记中删除 OldValuesParameterFormatString
属性, (或将其重置为其默认值, {0}
) 。 但是,在本教程中,我们仅使用 ObjectDataSource 来检索数据。 因此,我们不需要修改 ObjectDataSource 的 OldValuesParameterFormatString
属性值 (尽管这样做不会) 造成损害。
将默认 DataList 替换为自定义的 DataList ItemTemplate
后,页面上的声明性标记应如下所示:
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" RepeatColumns="2">
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>'></asp:Label>
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
OldValuesParameterFormatString="original_{0}">
</asp:ObjectDataSource>
花点时间通过浏览器查看进度。 如图 7 所示,DataList 在两列中显示每个产品的产品名称和单价。
图 7:产品名称和价格显示在 Two-Column DataList (单击以查看全尺寸图像)
注意
DataList 具有许多更新和删除过程所需的属性,这些值存储在视图状态中。 因此,在生成支持编辑或删除数据的 DataList 时,必须启用 DataList 的视图状态。
精明的读者可能记得,在创建可编辑的 GridViews、DetailsViews 和 FormViews 时,我们能够禁用视图状态。 这是因为 ASP.NET 2.0 Web 控件可以包含 控件状态,该状态在视图状态等回发中持久保存,但被认为是必要的。
在 GridView 中禁用视图状态只是省略了普通状态信息,但会保留控制状态 (,其中包括编辑和删除) 所需的状态。 DataList 是在 ASP.NET 1.x 时间范围内创建的,它不使用控制状态,因此必须启用视图状态。 有关 控件状态 的用途及其与视图状态的不同之处的详细信息,请参阅控件状态与视图状态。
步骤 4:添加编辑用户界面
GridView 控件由一组字段组成, (BoundFields、CheckBoxFields、TemplateFields 等) 。 这些字段可以根据其模式调整其呈现的标记。 例如,在只读模式下,BoundField 将其数据字段值显示为文本;当处于编辑模式时,它会呈现一个 TextBox Web 控件,该控件的 Text
属性被分配有数据字段值。
另一方面,DataList 使用模板呈现其项。 只读项使用 呈现, ItemTemplate
而编辑模式下的项则通过 EditItemTemplate
呈现。 此时,DataList 只有 一个 ItemTemplate
。 若要支持项级编辑功能,我们需要添加一个 EditItemTemplate
,其中包含要为可编辑项显示的标记。 在本教程中,我们将使用 TextBox Web 控件来编辑产品名称和单价。
EditItemTemplate
可以通过声明方式或通过Designer (从 DataList 智能标记) 选择“编辑模板”选项来创建 。 若要使用“编辑模板”选项,请先单击智能标记中的“编辑模板”链接,然后从下拉列表中选择 EditItemTemplate
该项。
图 8:选择使用 DataList (EditItemTemplate
单击以查看全尺寸图像)
接下来,键入“产品名称:”和“价格:”,然后将两个 TextBox 控件从工具箱拖到EditItemTemplate
Designer界面中。 将 TextBoxes ID
属性设置为 ProductName
和 UnitPrice
。
图 9:为“产品名称”和“价格”添加 TextBox (单击以查看全尺寸图像)
我们需要将相应的产品数据字段值绑定到 Text
两个 TextBox 的属性。 在 TextBoxs 智能标记中,单击“编辑数据绑定”链接,然后将相应的数据字段与 Text
属性相关联,如图 10 所示。
注意
将数据 UnitPrice
字段绑定到 price TextBox s Text
字段时,可以将其格式化为货币值 ({0:C}
) 、 () {0:N}
的一般数字,或将其设置为未格式化。
图 10:将 ProductName
和 UnitPrice
数据字段绑定到 Text
TextBox 的属性
请注意,图 10 中的“编辑数据绑定”对话框 如何不包括 在 GridView 或 DetailsView 中编辑 TemplateField 或 FormView 中的模板时存在的双向数据绑定复选框。 双向数据绑定功能允许在插入或UpdateParameters
更新数据时自动将输入到输入 Web 控件的值分配给相应的 ObjectDataSource sInsertParameters
。 DataList 不支持双向数据绑定,我们将在本教程的后面部分看到,在用户进行更改并准备好更新数据后,我们需要以编程方式访问这些 TextBoxes Text
属性,并将其值传递到 类中的ProductsBLL
相应UpdateProduct
方法。
最后,我们需要将“更新”和“取消”按钮添加到 EditItemTemplate
。 正如我们在 主控/详细信息使用带详细信息数据列表的主记录项目符号列表 教程中看到的那样,当从 Repeater 或 DataList 内单击设置了属性 CommandName
的 Button、LinkButton 或 ImageButton 时,将引发 Repeater 或 DataList 事件 ItemCommand
。 对于 DataList,如果 CommandName
属性设置为特定值,则也可能引发其他事件。 特殊 CommandName
属性值包括:
- 取消引发
CancelCommand
事件 - 编辑引发
EditCommand
事件 - 更新引发
UpdateCommand
事件
请记住,除了 事件之外,还会引发ItemCommand
这些事件。
将 添加到 EditItemTemplate
两个按钮 Web 控件,其中 CommandName
一个控件设置为“更新”,另一个设置为“取消”。 添加这两个按钮 Web 控件后,Designer应如下所示:
图 11:将“更新”和“取消”按钮添加到 EditItemTemplate
“ (单击以查看全尺寸图像)
完成之后, EditItemTemplate
DataList 的声明性标记应如下所示:
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" RepeatColumns="2">
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>' />
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<br />
</ItemTemplate>
<EditItemTemplate>
Product name:
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Eval("ProductName") %>' /><br />
Price:
<asp:TextBox ID="UnitPrice" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' /><br />
<br />
<asp:Button ID="UpdateProduct" runat="server"
CommandName="Update" Text="Update" />
<asp:Button ID="CancelUpdate" runat="server"
CommandName="Cancel" Text="Cancel" />
</EditItemTemplate>
</asp:DataList>
步骤 5:添加管道以进入编辑模式
此时,DataList 有一个通过其 EditItemTemplate
定义的编辑界面;但是,目前访问我们的页面的用户无法指示他想要编辑产品的信息。 我们需要向每个产品添加一个“编辑”按钮,单击后,该按钮将 DataList 项呈现在编辑模式下。 首先,通过 Designer 或以声明方式将“编辑”按钮添加到 ItemTemplate
。 请务必将“编辑”按钮的 CommandName
属性设置为“编辑”。
添加此“编辑”按钮后,请花点时间通过浏览器查看页面。 添加此项后,每个产品一览都应包含一个“编辑”按钮。
图 12:将“更新”和“取消”按钮添加到 EditItemTemplate
“ (单击以查看全尺寸图像)
单击该按钮会导致回发,但 不会 将产品列表置于编辑模式。 若要使产品可编辑,我们需要:
- 将 DataList 属性
EditItemIndex
设置为刚刚单击“编辑”按钮的 的索引DataListItem
。 - 将数据重新绑定到 DataList。 重新呈现 DataList 时,
DataListItem
其ItemIndex
与 DataListEditItemIndex
相对应的 将使用其EditItemTemplate
呈现。
由于在单击“编辑”按钮时会触发 DataList 事件 EditCommand
,因此使用以下代码创建 EditCommand
事件处理程序:
protected void DataList1_EditCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to the
// index of the DataListItem that was clicked
DataList1.EditItemIndex = e.Item.ItemIndex;
// Rebind the data to the DataList
DataList1.DataBind();
}
事件处理程序 EditCommand
作为其第二个输入参数传入类型的 DataListCommandEventArgs
对象中,该对象包含对 DataListItem
单击其“编辑”按钮 (e.Item
) 的引用。 事件处理程序首先将 DataList 设置为EditItemIndex
ItemIndex
可DataListItem
编辑的 ,然后通过调用 DataList 方法DataBind()
将数据重新绑定到 DataList。
添加此事件处理程序后,在浏览器中重新访问页面。 单击“编辑”按钮现在使单击的产品可编辑 (请参阅图 13) 。
图 13:单击“编辑”按钮使产品可编辑 (单击以查看全尺寸图像)
步骤 6:保存用户的更改
此时,单击已编辑的产品“更新”或“取消”按钮没有任何作用;若要添加此功能,我们需要为 DataList UpdateCommand
和 CancelCommand
事件创建事件处理程序。 首先创建 CancelCommand
事件处理程序,该事件处理程序将在单击已编辑的产品的“取消”按钮时执行,并且它的任务是将 DataList 返回到其预编辑状态。
若要让 DataList 在只读模式下呈现其所有项,我们需要:
- 将 DataList 属性
EditItemIndex
设置为不存在DataListItem
索引的索引。-1
是一个安全的选择,因为DataListItem
索引从 开始0
。 - 将数据重新绑定到 DataList。 由于没有
DataListItem
ItemIndex
es 对应于 DataList sEditItemIndex
,因此整个 DataList 将以只读模式呈现。
可以使用以下事件处理程序代码完成这些步骤:
protected void DataList1_CancelCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to -1
DataList1.EditItemIndex = -1;
// Rebind the data to the DataList
DataList1.DataBind();
}
添加此项后,单击“取消”按钮会将 DataList 返回到其预编辑状态。
我们需要完成的最后一个事件处理程序是 UpdateCommand
事件处理程序。 此事件处理程序需要:
- 以编程方式访问用户输入的产品名称和价格以及编辑的产品
ProductID
。 - 通过在 类中
ProductsBLL
调用相应的UpdateProduct
重载来启动更新过程。 - 将 DataList 属性
EditItemIndex
设置为不存在DataListItem
索引的索引。-1
是一个安全的选择,因为DataListItem
索引从 开始0
。 - 将数据重新绑定到 DataList。 由于没有
DataListItem
ItemIndex
es 对应于 DataList sEditItemIndex
,因此整个 DataList 将以只读模式呈现。
步骤 1 和 2 负责保存用户的更改;保存更改后,步骤 3 和 4 会将 DataList 返回到其预编辑状态,并且与事件处理程序中 CancelCommand
执行的步骤相同。
若要获取更新的产品名称和价格,需要使用 FindControl
方法以编程方式引用 中的 EditItemTemplate
TextBox Web 控件。 我们还需要获取已编辑的产品 ProductID
值。 最初将 ObjectDataSource 绑定到 DataList 时,Visual Studio 将 DataList 属性 DataKeyField
分配给数据源 (ProductID
) 的主键值。 然后,可以从 DataList 集合 DataKeys
中检索此值。 请花点时间确保 属性 DataKeyField
确实设置为 ProductID
。
以下代码实现四个步骤:
protected void DataList1_UpdateCommand(object source, DataListCommandEventArgs e)
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
// Read in the product name and price values
TextBox productName = (TextBox)e.Item.FindControl("ProductName");
TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");
string productNameValue = null;
if (productName.Text.Trim().Length > 0)
productNameValue = productName.Text.Trim();
decimal? unitPriceValue = null;
if (unitPrice.Text.Trim().Length > 0)
unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(),
System.Globalization.NumberStyles.Currency);
// Call the ProductsBLL's UpdateProduct method...
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);
// Revert the DataList back to its pre-editing state
DataList1.EditItemIndex = -1;
DataList1.DataBind();
}
事件处理程序首先从DataKeys
集合中读取已编辑的产品ProductID
。 接下来,引用 中的 EditItemTemplate
两个 TextBox,其 Text
属性存储在局部变量 productNameValue
和 unitPriceValue
中。 我们使用 Decimal.Parse()
方法从 UnitPrice
TextBox 读取值,以便如果输入的值具有货币符号,仍可将其正确转换为 Decimal
值。
注意
如果 TextBoxes Text 属性指定了值,则 和 TextBoxes 中的值ProductName
UnitPrice
仅分配给 productNameValue 和 unitPriceValue 变量。 否则,值 Nothing
用于变量,其效果是使用数据库 NULL
值更新数据。 也就是说,我们的代码处理将空字符串转换为数据库 NULL
值,这是 GridView、DetailsView 和 FormView 控件中编辑界面的默认行为。
读取值后, ProductsBLL
将调用 类 s UpdateProduct
方法,并传入产品名称、价格和 ProductID
。 事件处理程序通过使用与事件处理程序中 CancelCommand
完全相同的逻辑将 DataList 返回到其预编辑状态来完成。
完成 EditCommand
、 CancelCommand
和 UpdateCommand
事件处理程序后,访问者可以编辑产品的名称和价格。 图 14-16 显示了此编辑工作流的运行情况。
图 14:首次访问页面时,所有产品都处于 Read-Only 模式 (单击以查看全尺寸图像)
图 15:若要更新产品名称或价格,请单击“编辑”按钮 (单击以查看全尺寸图像)
图 16:更改值后,单击“更新”以返回到 Read-Only 模式 (单击以查看全尺寸图像)
步骤 7:添加删除功能
向 DataList 添加删除功能的步骤与添加编辑功能的步骤类似。 简言之,我们需要在单击时将“删除”按钮添加到 ItemTemplate
该按钮:
- 通过
DataKeys
集合读取相应产品的ProductID
。 - 通过调用
ProductsBLL
类 sDeleteProduct
方法执行删除。 - 将数据重新绑定到 DataList。
首先,将“删除”按钮添加到 ItemTemplate
。
单击时,如果 CommandName
按钮为“编辑”、“更新”或“取消”,则会引发 DataList 事件 ItemCommand
以及其他事件 (例如,在使用“编辑” EditCommand
时,还会引发) 事件。 同样,DataList CommandName
中属性设置为 Delete 的任何 Button、LinkButton 或 ImageButton 都会导致 DeleteCommand
事件与) 一起 ItemCommand
触发 (。
在 中的 ItemTemplate
“编辑”按钮旁边添加一个“删除”按钮,将其 CommandName
属性设置为“删除”。 添加此 Button 控件后,DataList 的 ItemTemplate
声明性语法应如下所示:
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>' />
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<asp:Button runat="server" id="EditProduct" CommandName="Edit"
Text="Edit" />
<asp:Button runat="server" id="DeleteProduct" CommandName="Delete"
Text="Delete" />
<br />
<br />
</ItemTemplate>
接下来,使用以下代码为 DataList 事件 DeleteCommand
创建事件处理程序:
protected void DataList1_DeleteCommand(object source, DataListCommandEventArgs e)
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
// Delete the data
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.DeleteProduct(productID);
// Rebind the data to the DataList
DataList1.DataBind();
}
单击“删除”按钮会导致回发并触发 DataList 事件 DeleteCommand
。 在事件处理程序中,从DataKeys
集合中访问单击的产品ProductID
值。 接下来,通过调用 ProductsBLL
类 s DeleteProduct
方法删除产品。
删除产品后,请务必将数据重新绑定到 DataList (DataList1.DataBind()
) ,否则 DataList 将继续显示刚刚删除的产品。
总结
虽然 DataList 缺少 GridView 享受的点和单击编辑和删除支持,但只需一小段代码即可对其进行增强以包含这些功能。 在本教程中,我们介绍了如何创建包含可删除以及可编辑其名称和价格的两列产品列表。 添加编辑和删除支持是将相应的 Web 控件包含在 和 EditItemTemplate
中ItemTemplate
,创建相应的事件处理程序,读取用户输入的值和主键值,并与业务逻辑层交互。
虽然我们在 DataList 中添加了基本的编辑和删除功能,但它缺乏更高级的功能。 例如,没有输入字段验证 - 如果用户输入的价格太昂贵,则在尝试将“太昂贵Decimal
”转换为 时将引发Decimal.Parse
异常。 同样,如果在更新业务逻辑或数据访问层中的数据时遇到问题,用户会看到标准错误屏幕。 如果不在“删除”按钮上进行任何确认,则意外删除产品的可能性太大。
在将来的教程中,我们将了解如何改进编辑用户体验。
编程快乐!
关于作者
斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。
特别感谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Zack Jones、Ken Pespisa 和 Randy Schmidt。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处mitchell@4GuysFromRolla.com放置一行。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈