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

作者 :Scott Mitchell

下载 PDF

在我们目前创建的界面中,用户可能会意外地通过单击“删除”按钮来删除数据,而他们打算单击“编辑”按钮。 在本教程中,我们将添加单击“删除”按钮时出现的客户端确认对话框。

简介

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

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

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

JavaScript 确认 (字符串) 方法显示模式、Client-Side 消息框

图 1:JavaScript confirm(string) 方法显示模式 Client-Side 消息框

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

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

注意

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

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

首先,将 FormView 添加到 文件夹中的页面ConfirmationOnDelete.aspxEditInsertDelete,将其绑定到新的 ObjectDataSource,该对象通过 ProductsBLL 类方法GetProducts()拉回产品信息。 此外,配置 ObjectDataSource,以便 ProductsBLL 类方法 DeleteProduct(productID) 映射到 ObjectDataSource s 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 属性。

由于它已绑定到仅支持删除的 ObjectDataSource 控件,因此 FormView ItemTemplate 仅提供“删除”按钮,缺少“新建”和“更新”按钮。 但是,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 事件调用 confirm (字符串) 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 时,只需配置其 属性以返回 JavaScript confirm(string) 函数的结果,即可与其OnClientClick关联确认对话框。 但是,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 Sub GridView1_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then
        ' reference the Delete LinkButton
        Dim db As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)

        ' Get information about the product bound to the row
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Row.DataItem, System.Data.DataRowView).Row, _
            Northwind.ProductsRow)

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

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

Dim obj As ButtonType = _
    CType(e.Row.Cells(commandFieldIndex).Controls(controlIndex), ButtonType)

ButtonType 是 CommandField - Button、LinkButton 或 ImageButton 使用的按钮类型。 默认情况下,CommandField 使用 LinkButtons,但这可以通过 CommandField 进行 ButtonType property自定义。 commandFieldIndex 是 GridView 集合中 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 的 CommandFields 转换为 TemplateFields。 这将生成一个 TemplateField,其中包含 ItemTemplate CommandField 中每个按钮的 LinkButton (或 Button 或 ImageButton) 。 这些按钮 OnClientClick 属性可以声明方式分配(正如我们在 FormView 中看到的),也可以使用以下模式在适当的 DataBound 事件处理程序中以编程方式访问:

Dim obj As ButtonType = CType(e.Row.FindControl("controlID"), ButtonType)

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

总结

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

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

编程快乐!

关于作者

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