下载 PDF

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

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

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

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

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

在表单提交期间,如果从客户端事件处理程序返回值 false ,则取消表单提交。 使用此功能,我们可以让 Delete 按钮的客户端 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.aspx 文件夹中的页面 EditInsertDelete ,将其绑定到通过 ProductsBLL 类方法 GetProducts() 拉回产品信息的新 ObjectDataSource。 还配置 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 s OldValuesParameterFormatString 属性。

由于它已绑定到仅支持删除的 ObjectDataSource 控件,因此 FormView 仅 ItemTemplate 提供“删除”按钮,缺少“新建”和“更新”按钮。 但是,FormView 的声明性标记包含一个多余的 EditItemTemplate 标记,可以 InsertItemTemplate删除该标记。 花点时间自定义 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 显示了到目前为止通过浏览器查看进度的屏幕截图。

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

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

创建 FormView 后,最后一步是配置“删除”按钮,以便当访问者单击该按钮时,将调用 JavaScript confirm(string) 函数。 通过使用 ASP.NET 2.0 的新增功能,可以将OnClientClick property客户端脚本添加到 Button、LinkButton 或 ImageButton 的客户端onclick事件。 由于我们想要返回函数的值 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 s Delete() 方法,最终删除数据库记录。

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

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

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

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

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

若要练习在 CommandField 中设置 OnClientClick “删除”按钮的属性 () ,请将 GridView 添加到页面。 将此 GridView 配置为使用 FormView 使用的相同 ObjectDataSource 控件。 此外,将 GridView s 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 包含一个可从 GridView 事件处理程序以编程方式访问的 RowDataBound Delete LinkButton 实例。 引用后,我们可以相应地设置其 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 使用 LinkButtons,但可以通过 CommandField s ButtonType property进行自定义。 commandFieldIndex 是 GridView 集合Columns中 CommandField 的序号索引,而 controlIndex 是 CommandField 集合Controls中 Delete 按钮的索引。 controlIndex 值取决于按钮相对于 CommandField 中的其他按钮的位置。 例如,如果 CommandField 中显示的唯一按钮是“删除”按钮,请使用索引 0。 但是,如果存在“删除”按钮之前的“编辑”按钮,请使用索引 2。 使用索引 2 的原因是,CommandField 在“删除”按钮之前添加了两个控件:“编辑”按钮和用于在“编辑”和“删除”按钮之间添加一些空格的 LiteralControl。

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

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

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

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

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

使用 TemplateFields

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

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

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

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

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

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

快乐编程!

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

上一页下一页