删除时添加客户端确认 (C#)

作者 :Scott Mitchell

下载 PDF

在我们到目前为止创建的界面中,当用户打算单击“编辑”按钮时,可以通过单击“删除”按钮意外删除数据。 在本教程中,我们将添加单击“删除”按钮时显示的客户端确认对话框。

简介

在过去的几个教程中,我们了解了如何使用应用程序体系结构、ObjectDataSource 和协同数据 Web 控件来提供插入、编辑和删除功能。 到目前为止,我们检查的删除接口由“删除”按钮组成,单击该按钮时,该按钮会导致回发并调用 ObjectDataSource 的 Delete() 方法。 然后, Delete() 方法从业务逻辑层调用配置的方法,该层将调用向下传播到数据访问层,向数据库发出实际 DELETE 语句。

虽然此用户界面允许访问者通过 GridView、DetailsView 或 FormView 控件删除记录,但当用户单击“删除”按钮时,它缺乏任何类型的确认。 如果用户在打算单击“编辑”时意外单击“删除”按钮,则将删除他们打算更新的记录。 为了帮助防止这种情况发生,在本教程中,我们将添加单击“删除”按钮时显示的客户端确认对话框。

JavaScript confirm(string) 函数将其字符串输入参数显示为具有两个按钮的模式对话框中的文本-“确定”和“取消” (请参阅图 1) 。 如果用户单击“确定false”,并且单击“取消”) ,函数confirm(string)将返回一个布尔值,具体取决于单击 (true单击的按钮。

JavaScript 确认 (字符串) 方法显示模式,Client-Side Messagebox

图 1:JavaScript confirm(string) 方法显示模式,Client-Side Messagebox

在表单提交期间,如果从客户端事件处理程序返回 的值 false ,则取消表单提交。 使用此功能,我们可以让“删除”按钮客户端 onclick 事件处理程序返回对 confirm("Are you sure you want to delete this product?")的调用的值。 如果用户单击“取消”, confirm(string) 将返回 false,从而导致表单提交取消。 如果没有回发,则不会删除单击“删除”按钮的产品。 但是,如果用户在确认对话框中单击“确定”,则回发将继续有增无减,产品将被删除。 有关此技术的详细信息 ,请参阅使用 JavaScript s confirm() 方法控制表单提交

如果使用模板,则添加必要的客户端脚本与使用 CommandField 时略有不同。 因此,在本教程中,我们将查看 FormView 和 GridView 示例。

注意

使用客户端确认技术(如本教程中讨论的技术)假定用户使用支持 JavaScript 且已启用 JavaScript 的浏览器进行访问。 如果上述任一假设都不适用于特定用户,则单击“删除”按钮将立即导致回发 (不显示确认消息框) 。

步骤 1:创建支持删除的 FormView

首先,将 FormView 添加到 文件夹中的页面ConfirmationOnDelete.aspxEditInsertDelete,将其绑定到新的 ObjectDataSource,该对象通过 ProductsBLL 类 s GetProducts() 方法拉回产品信息。 此外,配置 ObjectDataSource,以便类 ProductsBLL 方法 DeleteProduct(productID) 映射到 ObjectDataSource 的 Delete() 方法;确保 INSERT 和 UPDATE 选项卡下拉列表设置为 (None) 。 最后,检查 FormView 智能标记中的“启用分页”复选框。

执行这些步骤后,新的 ObjectDataSource 声明性标记将如下所示:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    DeleteMethod="DeleteProduct" OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <DeleteParameters>
        <asp:Parameter Name="productID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

与过去未使用乐观并发的示例一样,请花点时间清除 ObjectDataSource 的 OldValuesParameterFormatString 属性。

由于它已绑定到仅支持删除的 ItemTemplate ObjectDataSource 控件,因此 FormView 仅提供“删除”按钮,缺少“新建”和“更新”按钮。 但是,FormView 的声明性标记包括一个多余的 EditItemTemplateInsertItemTemplate,可以将其删除。 请花点时间自定义 , ItemTemplate 以便仅显示产品数据字段的子集。 我已将我的配置为在其供应商和类别名称上方的标题中 <h3> 显示产品名称 (以及“删除”按钮) 。

<asp:FormView ID="FormView1" AllowPaging="True" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" runat="server">
    <ItemTemplate>
        <h3><i><%# Eval("ProductName") %></i></h3>
        <b>Category:</b>
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'>
        </asp:Label><br />
        <b>Supplier:</b>
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
            CommandName="Delete" Text="Delete">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

通过这些更改,我们有了一个功能齐全的网页,允许用户一次切换一个产品,只需单击“删除”按钮即可删除产品。 图 2 显示了通过浏览器查看时到目前为止进度的屏幕截图。

FormView 显示有关单个产品的信息

图 2:FormView 显示有关单个产品的信息 (单击以查看全尺寸图像)

步骤 2:从删除按钮 Client-Side onclick 事件调用确认 (字符串) Function

创建 FormView 后,最后一步是配置“删除”按钮,以便访问者单击该按钮时调用 JavaScript confirm(string) 函数。 可以通过使用 OnClientClick property将客户端脚本添加到 Button、LinkButton 或 ImageButton s 客户端onclick事件,这是 ASP.NET 2.0 中的新增功能。 由于我们希望返回函数的值 confirm(string) ,因此只需将此属性设置为: return confirm('Are you certain that you want to delete this product?');

进行此更改后,Delete LinkButton 的声明性语法应如下所示:

<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
    CommandName="Delete" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete this product?');">
</asp:LinkButton>

这就是它的全部! 图 3 显示了此确认操作的屏幕截图。 单击“删除”按钮将显示确认对话框。 如果用户单击“取消”,则会取消回发,并且不会删除产品。 但是,如果用户单击“确定”,则继续回发,并调用 ObjectDataSource 方法 Delete() ,最终删除数据库记录。

注意

传入 JavaScript 函数的 confirm(string) 字符串用撇号 (而不是引号) 分隔。 在 JavaScript 中,可以使用任一字符分隔字符串。 我们在此处使用撇号,以便传入 confirm(string) 的字符串的分隔符不会与用于 OnClientClick 属性值的分隔符引入歧义。

单击“删除”按钮时,现在会显示确认

图 3:单击“删除”按钮时显示确认 (单击以查看全尺寸图像)

步骤 3:为 CommandField 中的“删除”按钮配置 OnClientClick 属性

直接在模板中使用 Button、LinkButton 或 ImageButton 时,只需将确认对话框的属性配置为 OnClientClick 返回 JavaScript confirm(string) 函数的结果即可与之关联。 但是,CommandField(将“删除”按钮字段添加到 GridView 或 DetailsView)没有 OnClientClick 可声明性设置的属性。 相反,我们必须以编程方式引用 GridView 或 DetailsView 中相应的 DataBound 事件处理程序中的“删除”按钮,然后在其中设置其 OnClientClick 属性。

注意

在相应的DataBound事件处理程序中设置“删除”按钮 s OnClientClick 属性时,我们有权访问绑定到当前记录的数据。 这意味着我们可以扩展确认消息以包含有关特定记录的详细信息,例如,“你确定要删除 Chai 产品吗?”使用数据绑定语法的模板中也可以进行此类自定义。

若要练习在 CommandField 中设置 OnClientClick “删除”按钮 () 的属性,请将 GridView 添加到页面。 将此 GridView 配置为使用 FormView 使用的同一 ObjectDataSource 控件。 此外,将 GridView 的 BoundFields 限制为仅包含产品名称、类别和供应商。 最后,检查 GridView 智能标记中的“启用删除”复选框。 这会将 CommandField 添加到 GridView 的 Columns 集合,其 ShowDeleteButton 属性设置为 true

进行这些更改后,GridView 的声明性标记应如下所示:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"
            SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True"
            SortExpression="SupplierName" />
    </Columns>
</asp:GridView>

CommandField 包含单个 Delete LinkButton 实例,可从 GridView 事件处理程序 RowDataBound 以编程方式访问该实例。 引用后,我们可以相应地设置其 OnClientClick 属性。 使用以下代码为 RowDataBound 事件创建事件处理程序:

protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
    if (e.Row.RowType == DataControlRowType.DataRow)
    {
        // reference the Delete LinkButton
        LinkButton db = (LinkButton)e.Row.Cells[0].Controls[0];

        // Get information about the product bound to the row
        Northwind.ProductsRow product =
            (Northwind.ProductsRow) ((System.Data.DataRowView) e.Row.DataItem).Row;

        db.OnClientClick = string.Format(
            "return confirm('Are you certain you want to delete the {0} product?');",
            product.ProductName.Replace("'", @"\'"));
    }
}

此事件处理程序处理数据行 (将具有“删除”按钮) 的数据行,并首先以编程方式引用“删除”按钮。 通常使用以下模式:

ButtonType obj = (ButtonType) e.Row.Cells[commandFieldIndex].Controls[controlIndex];

ButtonType 是 CommandField - Button、LinkButton 或 ImageButton 使用的按钮类型。 默认情况下,CommandField 使用 LinkButton,但可以通过 CommandField 进行 ButtonType property自定义。 commandFieldIndex 是 GridView s 集合中 CommandField 的Columns序号索引,而 controlIndex 是 CommandField 集合中“删除”按钮的Controls索引。 controlIndex 值取决于按钮相对于 CommandField 中其他按钮的位置。 例如,如果 CommandField 中显示的唯一按钮是“删除”按钮,请使用索引 0。 但是,如果“删除”按钮前面有“编辑”按钮,请使用索引 2。 使用索引 2 的原因是 CommandField 在“删除”按钮之前添加了两个控件:“编辑”按钮和用于在“编辑”和“删除”按钮之间添加一些空格的 LiteralControl。

对于我们的特定示例,CommandField 使用 LinkButtons,并且作为最左侧的字段, commandFieldIndex 为 0。 由于除了 CommandField 中的“删除”按钮外没有其他按钮,因此我们使用 controlIndex 为 0。

在引用 CommandField 中的“删除”按钮后,我们接下来会获取有关绑定到当前 GridView 行的产品的信息。 最后,我们将“删除”按钮的 OnClientClick 属性设置为相应的 JavaScript,其中包括产品名称。 由于传入函数的 confirm(string) JavaScript 字符串是使用撇号分隔的,因此必须转义产品名称中显示的任何撇号。 具体而言,产品名称中的任何撇号都使用“”\'进行转义。

完成这些更改后,单击 GridView 中的“删除”按钮将显示自定义的确认对话框, (请参阅图 4) 。 与 FormView 中的确认消息框一样,如果用户单击“取消”,则会取消回发,从而防止删除。

注意

此方法还可用于以编程方式访问 DetailsView 中 CommandField 中的“删除”按钮。 但是,对于 DetailsView,需要为 DataBound 事件创建事件处理程序,因为 DetailsView 没有 RowDataBound 事件。

单击 GridView 的“删除”按钮显示自定义确认对话框

图 4:单击 GridView 的删除按钮显示自定义确认对话框 (单击以查看全尺寸图像)

使用 TemplateFields

CommandField 的缺点之一是必须通过索引访问其按钮,并且生成的对象必须强制转换为相应的按钮类型 (Button、LinkButton 或 ImageButton) 。 使用“幻数”和硬编码类型会邀请在运行时之前无法发现的问题。 例如,如果你或其他开发人员在将来的某个时间点向 CommandField 添加新按钮, (如编辑按钮) 或更改 ButtonType 属性,则现有代码仍将编译,而不会出错,但访问页面可能会导致异常或意外行为,具体取决于代码的编写方式和所做的更改。

另一种方法是将 GridView 和 DetailsView 的 CommandField 转换为 TemplateFields。 这将生成一个 TemplateField,其中包含 ItemTemplate CommandField 中的每个按钮的 LinkButton (或 Button 或 ImageButton) 。 这些按钮 OnClientClick 属性可以按声明方式分配(正如我们在 FormView 中看到的),也可以使用以下模式在适当的 DataBound 事件处理程序中以编程方式访问:

ButtonType obj = (ButtonType) e.Row.FindControl("controlID");

其中 ,controlID 是按钮属性的值 ID 。 虽然此模式仍需要强制转换的硬编码类型,但它不需要索引,从而允许更改布局而不导致运行时错误。

总结

JavaScript confirm(string) 函数是控制表单提交工作流的常用技术。 执行时,函数将显示一个模式客户端对话框,其中包含两个按钮:“确定”和“取消”。 如果用户单击“确定”,则 confirm(string) 函数返回 true;单击“取消”将 false返回 。 此功能加上浏览器在提交过程中的事件处理程序返回 false时取消表单提交的行为,可用于在删除记录时显示确认消息框。

函数 confirm(string) 可以通过控件 的 属性与 Button Web 控件的客户端 onclick 事件处理程序 OnClientClick 相关联。 在模板中使用“删除”按钮时(无论是在 FormView 模板之一中还是在 DetailsView 或 GridView 中的 TemplateField 中),可以声明方式或编程方式设置此属性,如本教程中所示。

编程愉快!

关于作者

Scott Mitchell 是七本 ASP/ASP.NET 书籍的作者, 4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可以在 上联系 mitchell@4GuysFromRolla.com他, 也可以通过他的博客联系到他,该博客可在 http://ScottOnWriting.NET中找到。