在 DataList (VB) 中编辑和删除数据的概述

作者 :Scott Mitchell

下载 PDF

虽然 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 包含可在 Repeater 中找到的属性和事件,这些属性和事件可简化此类功能的添加。 因此,本教程和将来查看编辑和删除的内容将严格关注 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

为教程添加 ASP.NET 页面

图 1:为教程添加 ASP.NET 页

与其他文件夹中一样, Default.aspx 文件夹中会 EditDeleteDataList 列出其部分中的教程。 回想一下, SectionLevelTutorialListing.ascx 用户控件提供了此功能。 因此,通过将用户控件从解决方案资源管理器拖动到Default.aspx页面设计视图中,将此用户控件添加到 。

将 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 编辑和删除教程的项目。

站点地图现在包括用于 DataList 编辑和删除教程的条目

图 3:站点地图现在包含 DataList 编辑和删除教程的条目

步骤 2:检查更新和删除数据的方法

使用 GridView 编辑和删除数据非常简单,因为在背后,GridView 和 ObjectDataSource 协同工作。 如 检查与插入、更新和删除相关的事件 教程中所述,单击行的“更新”按钮时,GridView 会自动将其使用双向数据绑定 UpdateParameters 的字段分配给其 ObjectDataSource 的集合,然后调用该 ObjectDataSource 方法 Update()

遗憾的是,DataList 不提供任何此内置功能。 我们负责确保将用户的值分配给 ObjectDataSource 参数并调用其 Update() 方法。 为了帮助我们完成这一工作,DataList 提供了以下属性和事件:

使用这些属性和事件,可以使用四种方法来更新和删除 DataList 中的数据:

  1. 使用 ASP.NET 1.x 技术 ,DataList 在 ASP.NET 2.0 和 ObjectDataSources 之前就已存在,并且能够通过编程方式完全更新和删除数据。 此方法完全放弃 ObjectDataSource,并要求我们直接从业务逻辑层将数据绑定到 DataList,无论是检索要显示的数据,还是在更新或删除记录时。
  2. 在页面上使用单个 ObjectDataSource 控件进行选择、更新和删除, 而 DataList 缺少 GridView 固有的编辑和删除功能,我们没有理由无法自行添加它们。 使用此方法时,我们使用 ObjectDataSource 就像在 GridView 示例中一样,但必须为 DataList 事件 UpdateCommand 创建事件处理程序,在该事件中设置 ObjectDataSource s 参数并调用其 Update() 方法。
  3. 使用 ObjectDataSource 控件进行选择,但在使用选项 2 时直接针对 BLL 进行更新和删除 ,我们需要在 事件中 UpdateCommand 编写一些代码,分配参数值等。 相反,我们可以坚持使用 ObjectDataSource 进行选择,但直接对 BLL (进行更新和删除调用,如使用选项 1) 。 在我看来,通过与 BLL 直接交互来更新数据比分配 ObjectDataSource UpdateParameters 并调用其 Update() 方法更易读的代码。
  4. 通过 Multiple ObjectDataSources 使用 Declarative Means ,前三种方法都需要一些代码。 如果希望尽可能多地使用声明性语法,最后一种选择是在页面上包含多个 ObjectDataSources。 第一个 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 类。 若要检索 所有 产品,请在 SELECT 选项卡中选择 GetProducts() 方法。

将 ObjectDataSource 配置为使用 ProductsBLL 类

图 4:将 ObjectDataSource 配置为使用 ProductsBLL 类 (单击以查看全尺寸图像)

使用 GetProducts () 方法返回产品信息

图 5:使用 GetProducts() 方法返回产品信息 (单击以查看全尺寸图像)

与 GridView 一样,DataList 不用于插入新数据;因此,从“插入”选项卡的下拉列表中选择“ (无) ”选项。此外,为“更新”和“删除”选项卡选择“ (”无“) ,因为更新和删除将通过 BLL 以编程方式执行。

确认 ObjectDataSource 的 INSERT、UPDATE 和 DELETE 选项卡中的 Drop-Down Lists 设置为 (None)

图 6:确认 ObjectDataSource 的 INSERT、UPDATE 和 DELETE 选项卡中的 Drop-Down Lists 设置为 (None) (单击以查看全尺寸图像)

配置 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 在两列中显示每个产品的产品名称和单价。

“产品名称”和“价格”显示在 Two-Column DataList 中

图 7:“产品名称”和“价格”显示在 Two-Column DataList (单击以查看全尺寸图像)

注意

DataList 具有许多更新和删除过程所需的属性,这些值存储在视图状态中。 因此,在构建支持编辑或删除数据的 DataList 时,必须启用 DataList 的视图状态。

精明的读者可能还记得,在创建可编辑的 GridViews、DetailsViews 和 FormView 时,我们能够禁用视图状态。 这是因为 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 然后从下拉列表中选择该项。

选择使用 DataList 的 EditItemTemplate

图 8:选择使用 DataList EditItemTemplate (单击以查看全尺寸图像)

接下来,键入“产品名称:”和“价格:”,然后将两个 TextBox 控件从“工具箱”拖动到EditItemTemplateDesigner界面中。 将 TextBoxes ID 属性设置为 ProductNameUnitPrice

为产品名称和价格添加 TextBox

图 9:为“产品名称”和“价格”添加 TextBox (单击以查看全尺寸图像)

我们需要将相应的产品数据字段值绑定到 Text 两个 TextBox 的属性。 在 TextBoxes 智能标记中,单击“编辑数据绑定”链接,然后将相应的数据字段与 Text 属性相关联,如图 10 所示。

注意

将数据 UnitPrice 字段绑定到 price TextBox s Text 字段时,可以将其设置为货币值 ({0:C}) 、常规数字 ({0:N}) ,或将其设置为未格式化。

将 ProductName 和 UnitPrice 数据字段绑定到 TextBox 的文本属性

图 10:将 ProductNameUnitPrice 数据字段绑定到 Text TextBoxs 的属性

请注意,图 10 中的“编辑数据绑定”对话框 不包括 在 GridView 或 DetailsView 中编辑 TemplateField 或 FormView 中的模板时出现的双向数据绑定复选框。 双向数据绑定功能允许在输入 Web 控件中输入的值自动分配给相应的 ObjectDataSource s InsertParameters ,或者在 UpdateParameters 插入或更新数据时。 DataList 不支持双向数据绑定,我们将在本教程的后面部分看到,在用户进行更改并准备好更新数据后,我们需要以编程方式访问这些 TextBoxes Text 属性,并将其值传递给 类中的ProductsBLL相应UpdateProduct方法。

最后,我们需要将“更新”和“取消”按钮添加到 EditItemTemplate。 正如我们在 大纲/详细信息使用项目符号主记录列表和详细信息 DataList 教程中看到的那样,当从 Repeater 或 DataList 内单击设置了属性 CommandName 的 Button、LinkButton 或 ImageButton 时,将引发 Repeater 或 DataList 事件 ItemCommand 。 对于 DataList,如果 属性 CommandName 设置为特定值,则可能还会引发其他事件。 特殊 CommandName 属性值包括:

  • Cancel 引发 CancelCommand 事件
  • 编辑引发 EditCommand 事件
  • 更新会 UpdateCommand 引发 事件

请记住,除了 事件之外,ItemCommand还会引发这些事件。

将 添加到 EditItemTemplate 两个按钮 Web 控件,其中 CommandName 一个控件设置为“更新”,另一个控件设置为“取消”。 添加这两个按钮 Web 控件后,Designer应如下所示:

显示 DataList EditItemTemplate 的屏幕截图,其中添加了“更新”和“取消”按钮。

图 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 设置为“编辑”。

添加此“编辑”按钮后,请花点时间通过浏览器查看页面。 添加此项后,每个产品一览应包含一个“编辑”按钮。

显示 DataList EditItemTemplate 的屏幕截图,其中添加了“编辑”按钮。

图 12:将“更新”和“取消”按钮添加到 EditItemTemplate (单击以查看全尺寸图像)

单击该按钮会导致回发,但 不会 将产品列表置于编辑模式。 若要使产品可编辑,我们需要:

  1. 将 DataList 属性EditItemIndex设置为刚刚单击了“编辑”按钮的 的索引DataListItem
  2. 将数据重新绑定到 DataList。 重新呈现 DataList 时, DataListItemItemIndex 与 DataList EditItemIndex 对应的 将使用其 EditItemTemplate呈现。

由于单击“编辑”按钮时会触发 DataList 事件 EditCommand ,因此使用以下代码创建 EditCommand 事件处理程序:

Protected Sub DataList1_EditCommand(source As Object, e As DataListCommandEventArgs) _
    Handles DataList1.EditCommand
    ' 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()
End Sub

EditCommand事件处理程序作为其第二个输入参数传入类型的DataListCommandEventArgs对象,其中包括对单击其“编辑”按钮 (e.Item) 的 引用DataListItem。 事件处理程序首先将 DataList EditItemIndex 设置为 ItemIndexDataListItem 编辑的 的 ,然后通过调用 DataList 方法 DataBind() 将数据重新绑定到 DataList。

添加此事件处理程序后,在浏览器中重新访问页面。 单击“编辑”按钮现在使单击的产品可编辑 (请参阅图 13) 。

单击“编辑”按钮使产品可编辑

图 13:单击“编辑”按钮使产品可编辑 (单击以查看全尺寸图像)

步骤 6:保存用户的更改

单击已编辑的产品“更新”或“取消”按钮此时没有任何作用;若要添加此功能,我们需要为 DataList UpdateCommandCancelCommand 事件创建事件处理程序。 首先创建 CancelCommand 事件处理程序,该事件处理程序将在单击已编辑的产品“取消”按钮时执行,并执行任务是将 DataList 返回到其预编辑状态。

若要让 DataList 以只读模式呈现其所有项,我们需要:

  1. 将 DataList 属性EditItemIndex设置为不存在DataListItem的索引的索引。 -1 是安全的选择,因为 DataListItem 索引从 开始 0
  2. 将数据重新绑定到 DataList。 由于没有 DataListItemItemIndex es 对应于 DataList , EditItemIndex因此整个 DataList 将以只读模式呈现。

可以使用以下事件处理程序代码完成这些步骤:

Protected Sub DataList1_CancelCommand(source As Object, e As DataListCommandEventArgs) _
    Handles DataList1.CancelCommand
    ' Set the DataList's EditItemIndex property to -1
    DataList1.EditItemIndex = -1
    ' Rebind the data to the DataList
    DataList1.DataBind()
End Sub

添加此项后,单击“取消”按钮会将 DataList 返回到其预编辑状态。

我们需要完成的最后一个 UpdateCommand 事件处理程序是 事件处理程序。 此事件处理程序需要:

  1. 以编程方式访问用户输入的产品名称和价格以及编辑的产品 ProductID
  2. 通过在 类中ProductsBLL调用相应的UpdateProduct重载来启动更新过程。
  3. 将 DataList 属性EditItemIndex设置为不存在DataListItem的索引的索引。 -1 是安全的选择,因为 DataListItem 索引从 开始 0
  4. 将数据重新绑定到 DataList。 由于没有 DataListItemItemIndex es 对应于 DataList , EditItemIndex因此整个 DataList 将以只读模式呈现。

步骤 1 和 2 负责保存用户的更改;步骤 3 和 4 在保存更改后,DataList 将返回到其预编辑状态,并且与在事件处理程序中 CancelCommand 执行的步骤相同。

若要获取更新的产品名称和价格,需要使用 FindControl 方法以编程方式引用 中的 EditItemTemplateTextBox Web 控件。 我们还需要获取已编辑的产品值 ProductID 。 当我们最初将 ObjectDataSource 绑定到 DataList 时,Visual Studio 将 DataList 属性 DataKeyField 分配给数据源 (ProductID) 的主键值。 然后,可以从 DataList 集合 DataKeys 中检索此值。 请花点时间确保 属性 DataKeyField 确实设置为 ProductID

以下代码实现四个步骤:

Protected Sub DataList1_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles DataList1.UpdateCommand
    ' Read in the ProductID from the DataKeys collection
    Dim productID As Integer = Convert.ToInt32(DataList1.DataKeys(e.Item.ItemIndex))
    ' Read in the product name and price values
    Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
    Dim unitPrice As TextBox = CType(e.Item.FindControl("UnitPrice"), TextBox)
    Dim productNameValue As String = Nothing
    If productName.Text.Trim().Length > 0 Then
        productNameValue = productName.Text.Trim()
    End If
    Dim unitPriceValue As Nullable(Of Decimal) = Nothing
    If unitPrice.Text.Trim().Length > 0 Then
        unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(), NumberStyles.Currency)
    End If
    ' Call the ProductsBLL's UpdateProduct method...
    Dim productsAPI As New ProductsBLL()
    productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID)
    ' Revert the DataList back to its pre-editing state
    DataList1.EditItemIndex = -1
    DataList1.DataBind()
End Sub

事件处理程序首先从集合中读取已编辑的产品ProductIDDataKeys。 接下来,引用 中的 EditItemTemplate 两个 TextBox,其 Text 属性存储在局部变量 productNameValueunitPriceValue中。 我们使用 Decimal.Parse() 方法从 UnitPrice TextBox 读取值,以便如果输入的值具有货币符号,仍可将其正确转换为 Decimal 值。

注意

如果 TextBoxes Text 属性指定了值,则和 TextBoxes 中的ProductNameUnitPrice值仅分配给 productNameValue 和 unitPriceValue 变量。 否则, Nothing 值将用于变量,这会影响使用数据库 NULL 值更新数据。 也就是说,我们的代码处理将空字符串转换为数据库 NULL 值,这是 GridView、DetailsView 和 FormView 控件中编辑界面的默认行为。

读取值后, ProductsBLL 将调用 类 s UpdateProduct 方法,并传入产品名称、价格和 ProductID。 事件处理程序通过使用与事件处理程序中 CancelCommand 完全相同的逻辑将 DataList 返回到其预编辑状态来完成。

完成 EditCommandCancelCommandUpdateCommand 事件处理程序后,访问者可以编辑产品的名称和价格。 图 14-16 显示了此编辑工作流的运行情况。

首次访问页面时,所有产品都处于 Read-Only 模式

图 14:首次访问页面时,所有产品都处于 Read-Only 模式 (单击以查看全尺寸图像)

若要更新产品名称或价格,请单击“编辑”按钮

图 15:若要更新产品名称或价格,请单击“编辑”按钮 (单击以查看全尺寸图像)

更改值后,单击“更新”以返回到 Read-Only 模式

图 16:更改值后,单击“更新”以返回到 Read-Only 模式 (单击以查看全尺寸图像)

步骤 7:添加删除功能

向 DataList 添加删除功能的步骤与添加编辑功能的步骤类似。 简而言之,我们需要在单击时将“删除”按钮添加到 ItemTemplate 该按钮:

  1. 通过 DataKeys 集合读取相应产品的 ProductID
  2. 通过调用 ProductsBLL 类 s DeleteProduct 方法执行删除。
  3. 将数据重新绑定到 DataList。

首先,将“删除”按钮添加到 。ItemTemplate

单击时,为 CommandName Edit、Update 或 Cancel 的 Button 将引发 DataList 事件 ItemCommand 以及其他事件 (例如,使用“编辑” EditCommand 时,也会引发) 事件。 同样,DataList CommandName 中属性设置为 Delete 的任何 Button、LinkButton 或 ImageButton 都会导致 DeleteCommand 事件与) 一起 ItemCommand 触发 (。

在 的 ItemTemplate“编辑”按钮旁边添加一个“删除”按钮,将其 CommandName 属性设置为“删除”。 添加此按钮控件后,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 Sub DataList1_DeleteCommand(source As Object, e As DataListCommandEventArgs) _
    Handles DataList1.DeleteCommand
    ' Read in the ProductID from the DataKeys collection
    Dim productID As Integer = Convert.ToInt32(DataList1.DataKeys(e.Item.ItemIndex))
    ' Delete the data
    Dim productsAPI As New ProductsBLL()
    productsAPI.DeleteProduct(productID)
    ' Rebind the data to the DataList
    DataList1.DataBind()
End Sub

单击“删除”按钮会导致回发并触发 DataList 事件 DeleteCommand 。 在事件处理程序中,从DataKeys集合访问单击ProductID的产品值。 接下来,通过调用 ProductsBLL 类 s DeleteProduct 方法删除产品。

删除产品后,请务必将数据重新绑定到 dataList (DataList1.DataBind()) ,否则 DataList 将继续显示刚刚删除的产品。

总结

虽然 DataList 缺少 GridView 所享受的点和单击编辑和删除支持,但只需一点代码,就可以增强它以包含这些功能。 在本教程中,我们了解了如何创建一个包含两列的产品列表,这些列表包含可删除的产品以及可以编辑其名称和价格的产品。 添加编辑和删除支持需要将相应的 Web 控件包含在 和 EditItemTemplateItemTemplate,创建相应的事件处理程序,读取用户输入的值和主键值,并与业务逻辑层进行交互。

虽然我们在 DataList 中添加了基本的编辑和删除功能,但它缺少更高级的功能。 例如,没有输入字段验证 - 如果用户输入的价格太高,则在尝试将“太贵Decimal”转换为 时将引发Decimal.Parse异常。 同样,如果在更新业务逻辑或数据访问层的数据时遇到问题,用户会看到标准错误屏幕。 如果在“删除”按钮上没有任何确认,则意外删除产品的可能性太大。

在以后的教程中,我们将了解如何改进编辑用户体验。

编程愉快!

关于作者

Scott Mitchell 是七本 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。