编辑和删除 DataList 中的数据概述 (C#)

作者 :斯科特·米切尔

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

步骤 1:创建编辑和删除教程网页

在开始探索如何更新和删除 DataList 中的数据之前,让我们先花点时间在网站项目中创建 ASP.NET 页面,本教程和接下来需要几个页面。 首先添加名为 <a0/a0> 的新文件夹。 接下来,将以下 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.aspxEditDeleteDataList 文件夹中的教程将列出其部分中的教程。 回想一下, SectionLevelTutorialListing.ascx 用户控件提供了此功能。 因此,通过将此用户控件从解决方案资源管理器拖动到Default.aspx页面的设计视图中,将其添加到该控件。

将 SectionLevelTutorialListing.ascx 用户控件添加到 Default.aspx

图 2:将用户控件Default.aspx添加到 SectionLevelTutorialListing.ascx单击以查看全尺寸图像

最后,将页面添加为文件的条目 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 参数并调用其 Update() 方法。
  3. 使用 ObjectDataSource 控件进行选择,但在使用选项 2 时直接针对 BLL 进行更新和删除,我们需要在事件中 UpdateCommand 编写一些代码、分配参数值等。 相反,我们可以继续使用 ObjectDataSource 进行选择,但直接对 BLL 进行更新和删除调用(如选项 1)。 在我看来,通过直接与 BLL 交互来更新数据会导致比分配 ObjectDataSource s UpdateParameters 和调用其 Update() 方法更具可读性的代码。
  4. 通过多个 ObjectDataSource 使用声明性手段时,上述三种方法都需要一点代码。 如果宁愿继续使用尽可能多的声明性语法,最后一个选项是在页面上包括多个 ObjectDataSources。 第一个 ObjectDataSource 从 BLL 检索数据,并将其绑定到 DataList。 为了更新,将添加另一个 ObjectDataSource,但直接添加到 DataList s EditItemTemplate中。 若要包括删除支持,还需要在 ItemTemplate/> 中添加另一个 ObjectDataSource。 使用此方法,这些嵌入的 ObjectDataSource 用于 ControlParameters 以声明方式将 ObjectDataSource 参数绑定到用户输入控件(而不必在 DataList 事件处理程序 UpdateCommand 中以编程方式指定这些参数)。 此方法仍然需要一些代码,我们需要调用嵌入式 ObjectDataSource s Update()Delete() 命令,但需要远远低于其他三种方法。 此处的缺点是,多个 ObjectDataSources 在页面上杂乱无章,从整体可读性中减去。

如果强制只使用这些方法之一,我会选择选项 1,因为它提供最大的灵活性,并且因为 DataList 最初旨在适应此模式。 虽然 DataList 已扩展为使用 ASP.NET 2.0 数据源控件,但它没有官方 ASP.NET 2.0 数据 Web 控件(GridView、DetailsView 和 FormView)的所有扩展点或功能。 不过,选项 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() 方法返回产品信息(单击以查看全尺寸图像

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

确认 ObjectDataSource 的 INSERT、UPDATE 和 DELETE 选项卡中的下拉列表已设置为 (无)

图 6:确认 ObjectDataSource 的 INSERT、UPDATE 和 DELETE 选项卡中的下拉列表已设置为 (无) (单击以查看全尺寸图像

配置 ObjectDataSource 后,单击“完成”,返回到设计器。 如前例所示,完成 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 在两列中显示每个产品的产品名称和单价。

产品名称和价格显示在双列 DataList 中

图 7:产品名称和价格显示在双列数据列表中(单击以查看全尺寸图像

注意

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 模板(通过从 DataList 智能标记中选择“编辑模板”选项)。 若要使用“编辑模板”选项,请先单击智能标记中的“编辑模板”链接,然后从下拉列表中选择该项 EditItemTemplate

选择使用 DataList s EditItemTemplate

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

接下来,键入产品名称:和 Price:,然后将工具箱中的两个 TextBox 控件拖到 EditItemTemplate 设计器上的界面中。 将 TextBoxes ID 属性设置为 ProductNameUnitPrice

为产品名称和价格添加 TextBox

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

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

注意

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

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

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

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

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

  • 取消引发 CancelCommand 事件
  • 编辑引发 EditCommand 事件
  • 更新引发 UpdateCommand 事件

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

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

显示 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 项处于编辑模式的每个产品。 首先,通过设计器或以声明方式将“编辑”按钮添加到 ItemTemplate该按钮。 请务必将“编辑”按钮的属性 CommandName 设置为“编辑”。

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

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

图 12:向 /> 添加“更新”和“取消”按钮 EditItemTemplate单击以查看全尺寸图像

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

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

由于单击“编辑”按钮时触发 DataList s 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 设置为可DataListItem编辑的,EditItemIndexItemIndex然后通过调用 DataList 方法DataBind()将数据重新绑定到 DataList。

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

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

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

步骤 6:保存用户更改

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

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

  1. 将 DataList s EditItemIndex 属性 设置为不存在 DataListItem 索引的索引。 -1 是一个安全选择,因为 DataListItem 索引从此 0开始。
  2. 将数据重新绑定到 DataList。 由于没有 DataListItem ItemIndex es 对应于 DataList s EditItemIndex,因此整个 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 事件处理程序。 此事件处理程序需要:

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

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

若要获取更新的产品名称和价格,我们需要使用 FindControl 该方法以编程方式引用文本框中 EditItemTemplate的 Web 控件。 我们还需要获取编辑的产品 ProductID 值。 当我们最初将 ObjectDataSource 绑定到 DataList 时,Visual Studio 将 DataList s 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。 接下来,将引用Text其中的EditItemTemplate两个 TextBox 及其存储在局部变量中的属性,productNameValue以及 unitPriceValue。 我们使用该方法 Decimal.Parse()UnitPrice TextBox 读取值,以便输入的值具有货币符号,仍可将其正确转换为 Decimal 值。

注意

如果 TextBoxes 文本属性指定了值,则来自 TextBoxes 和 UnitPrice TextBoxes 的值ProductName仅分配给 productNameValue 和 unitPriceValue 变量。 否则,值 Nothing 用于变量,其效果是使用数据库 NULL 值更新数据。 也就是说,我们的代码将空字符串转换为数据库 NULL 值,这是 GridView、DetailsView 和 FormView 控件中编辑接口的默认行为。

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

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

首次访问页面时,所有产品都处于只读模式

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

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

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

更改值后,单击“更新”以返回到只读模式

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

步骤 7:添加删除功能

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

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

让我们首先向 <a0/> 添加“删除”按钮。

单击时,“ CommandName 编辑”、“更新”或“取消”按钮会引发 DataList 事件 ItemCommand 以及其他事件(例如,使用“编辑” EditCommand 时也会引发该事件)。 同样,DataList 中任何 Button、LinkButton 或 ImageButton 的属性 CommandName 设置为 Delete 会导致 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 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 类的方法 DeleteProduct 删除产品。

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

总结

虽然 DataList 缺少该点并单击 GridView 喜欢的编辑和删除支持,但可以增强它以包含这些功能的简短代码。 在本教程中,我们了解了如何创建可删除的产品的两列列表,以及可编辑其名称和价格。 添加编辑和删除支持是包括相应 Web 控件ItemTemplateEditItemTemplate以及创建相应的事件处理程序、读取用户输入值和主键值以及与业务逻辑层交互的问题。

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

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

快乐编程!

关于作者

斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0。 他可以通过他的博客联系到mitchell@4GuysFromRolla.com他,可以在该博客中找到http://ScottOnWriting.NET

特别感谢

本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Zack Jones、Ken Pespisa 和 Randy Schmidt。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请把我扔一条线。mitchell@4GuysFromRolla.com