添加和响应 GridView 的按钮 (VB)

作者 :Scott Mitchell

下载 PDF

本教程介绍如何将自定义按钮添加到模板和 GridView 或 DetailsView 控件的字段。 具体而言,我们将生成一个具有 FormView 的接口,该界面允许用户翻阅供应商。

简介

虽然许多报告方案涉及对报表数据的只读访问,但报表包含基于显示的数据执行操作的能力并不少见。 这通常涉及添加 Button、LinkButton 或 ImageButton Web 控件,其中每个记录显示在报表中,单击这些记录时会导致回发并调用某些服务器端代码。 按记录编辑和删除数据是最常见的示例。 事实上,从 插入、更新和删除数据概述 教程开始,编辑和删除操作非常常见,GridView、DetailsView 和 FormView 控件无需编写一行代码即可支持此类功能。

除了“编辑”和“删除”按钮外,GridView、DetailsView 和 FormView 控件还可以包括按钮、LinkButton 或 ImageButton,单击这些按钮时执行一些自定义服务器端逻辑。 本教程介绍如何将自定义按钮添加到模板和 GridView 或 DetailsView 控件的字段。 具体而言,我们将生成一个具有 FormView 的接口,该界面允许用户翻阅供应商。 对于给定的供应商,FormView 将显示有关供应商的信息以及按钮 Web 控件,如果单击该按钮,则将其所有相关产品标记为已停产。 此外,GridView 列出了所选供应商提供的产品,每一行都包含“提高价格”和“折扣价格”按钮,如果单击这些按钮,可提高或减少产品 UnitPrice 10%, (请参阅图 1) 。

FormView 和 GridView 都包含执行自定义操作的按钮

图 1:FormView 和 GridView 都包含执行自定义操作的按钮 (单击以查看全尺寸图像)

步骤 1:添加按钮教程网页

在了解如何添加自定义按钮之前,让我们先花点时间在网站项目中创建本教程所需的 ASP.NET 页面。 首先添加名为 CustomButtons的新文件夹。 接下来,将以下两个 ASP.NET 页添加到该文件夹,确保将每个页面与 Site.master 母版页相关联:

  • Default.aspx
  • CustomButtons.aspx

为自定义 Buttons-Related 教程添加 ASP.NET 页面

图 2:为自定义 Buttons-Related 教程添加 ASP.NET 页面

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

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

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

最后,将页面作为条目添加到文件中 Web.sitemap 。 具体而言,在分页和排序 <siteMapNode>之后添加以下标记:

<siteMapNode
    title="Adding Custom Buttons"
    description="Samples of Reports that Include Buttons for Performing
                  Server-Side Actions"
    url="~/CustomButtons/Default.aspx">
    <siteMapNode
        title="Using ButtonFields and Buttons in Templates"
        description="Examines how to add custom Buttons, LinkButtons,
                      or ImageButtons as ButtonFields or within templates."
        url="~/CustomButtons/CustomButtons.aspx" />
</siteMapNode>

更新 Web.sitemap后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包含用于编辑、插入和删除教程的项目。

站点地图现在包括自定义按钮教程的条目

图 4:站点地图现在包含自定义按钮教程的条目

步骤 2:添加Lists供应商的 FormView

让我们通过添加列出供应商的 FormView 开始学习本教程。 如简介中所述,此 FormView 将允许用户分页浏览供应商,并在 GridView 中显示供应商提供的产品。 此外,此 FormView 将包含一个按钮,单击该按钮会将所有供应商产品标记为已停产。 在关注将自定义按钮添加到 FormView 之前,让我们先创建 FormView,使其显示供应商信息。

首先打开 CustomButtons.aspx 文件夹中的页面 CustomButtons 。 通过将 FormView 从工具箱拖到Designer,并将其ID属性设置为 Suppliers,将 FormView 添加到页面。 在 FormView 智能标记中,选择创建名为 SuppliersDataSource的新 ObjectDataSource。

创建新的对象DataSource 名为 SuppliersDataSource

图 5:新建名为 SuppliersDataSource 的对象数据源 (单击以查看全尺寸图像)

配置此新的 ObjectDataSource,使其从 SuppliersBLL 类的 GetSuppliers() 方法进行查询 (请参阅图 6) 。 由于此 FormView 不提供用于更新供应商信息的界面,因此从“更新”选项卡的下拉列表中选择“ (无) ”选项。

将数据源配置为使用 SuppliersBLL 类 getSuppliers () 方法

图 6:将数据源配置为使用 SuppliersBLL 类方法 GetSuppliers() (单击以查看全尺寸图像)

配置 ObjectDataSource 后,Visual Studio 将为 FormView 生成 InsertItemTemplateEditItemTemplateItemTemplateInsertItemTemplate删除 和 EditItemTemplate 并修改 ,ItemTemplate使其仅显示供应商的公司名称和电话号码。 最后,通过选中其智能标记 (中的“启用分页”复选框或将其 AllowPaging 属性设置为 True “) ”来启用 FormView 的分页支持。 进行这些更改后,页面声明性标记应如下所示:

<asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
    DataSourceID="SuppliersDataSource" EnableViewState="False" AllowPaging="True">
    <ItemTemplate>
        <h3>
            <asp:Label ID="CompanyName" runat="server"
                Text='<%# Bind("CompanyName") %>' />
        </h3>
        <b>Phone:</b>
        <asp:Label ID="PhoneLabel" runat="server" Text='<%# Bind("Phone") %>' />
    </ItemTemplate>
</asp:FormView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

图 7 显示了通过浏览器查看时CustomButtons.aspx页。

FormView Lists当前所选供应商的“公司名称”和“电话”字段

图 7:FormView ListsCompanyName当前所选供应商中的 和 Phone 字段 (单击以查看全尺寸图像)

步骤 3:添加Lists所选供应商产品的 GridView

在将“停用所有产品”按钮添加到 FormView 模板之前,让我们先在 FormView 下面添加一个 GridView,其中列出了所选供应商提供的产品。 为此,请将 GridView 添加到页面,将其 ID 属性设置为 SuppliersProducts,并添加名为 SuppliersProductsDataSource的新 ObjectDataSource。

创建新的对象DataSource 命名的 SuppliersProductsDataSource

图 8:新建名为 SuppliersProductsDataSource 的对象数据源 (单击 以查看全尺寸图像)

配置此 ObjectDataSource 以使用 ProductsBLL 类 s GetProductsBySupplierID(supplierID) 方法 (请参阅图 9) 。 虽然此 GridView 允许调整产品价格,但它不会使用内置编辑或删除 GridView 中的功能。 因此,我们可以将“objectDataSource”更新“、”插入“和”删除“选项卡的下拉列表设置为 (”无“) 。

将数据源配置为使用 ProductsBLL 类 getProductsBySupplierID (supplierID) 方法

图 9:将数据源配置为使用 ProductsBLL 类 s GetProductsBySupplierID(supplierID) 方法 (单击以查看全尺寸图像)

GetProductsBySupplierID(supplierID)由于 方法接受输入参数,因此 ObjectDataSource 向导会提示我们输入此参数值的源。 若要从 FormView 传入 SupplierID 值,请将“参数源”下拉列表设置为 Control,将 ControlID 下拉列表设置为 Suppliers (步骤 2) 中创建的 FormView 的 ID。

指示 supplierID 参数应来自 Suppliers FormView 控件

图 10:指示 supplierID 参数应来自 Suppliers FormView 控件 (单击以查看全尺寸图像)

完成 ObjectDataSource 向导后,GridView 将包含每个产品数据字段的 BoundField 或 CheckBoxField。 让我们向下剪裁,以便仅 ProductName 显示 和 UnitPrice BoundFields 以及 Discontinued CheckBoxField;此外,让我们设置 UnitPrice BoundField 的格式,使其文本的格式设置为货币。 GridView 和 SuppliersProductsDataSource ObjectDataSource 的声明性标记应类似于以下标记:

<asp:GridView ID="SuppliersProducts" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
    EnableViewState="False" runat="server">
    <Columns>
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:C}"
            HtmlEncode="False" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersProductsDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
    <SelectParameters>
        <asp:ControlParameter ControlID="Suppliers" Name="supplierID"
            PropertyName="SelectedValue" Type="Int32" />
    </SelectParameters>
</asp:ObjectDataSource>

此时,我们的教程会显示主报表/详细信息报表,允许用户从顶部的 FormView 中选择供应商,并通过底部的 GridView 查看该供应商提供的产品。 图 11 显示了从 FormView 中选择 Tokyo Traders 供应商时此页面的屏幕截图。

所选供应商的产品显示在 GridView 中

图 11:所选供应商的产品显示在 GridView 中 (单击以查看全尺寸图像)

步骤 4:创建 DAL 和 BLL 方法来停用供应商的所有产品

在向 FormView 添加按钮(单击该按钮时停止所有供应商产品)之前,首先需要向 DAL 和 BLL 添加执行此操作的方法。 具体而言,此方法将命名为 DiscontinueAllProductsForSupplier(supplierID)。 单击 FormView 按钮时,我们将在业务逻辑层中调用此方法,传入所选供应商 ; SupplierID然后,BLL 将调用相应的数据访问层方法,该方法将向数据库发出 UPDATE 停止指定供应商产品的语句。

正如我们在前面的教程中所做的那样,我们将使用自下而上的方法,首先创建 DAL 方法,然后创建 BLL 方法,最后在 ASP.NET 页中实现功能。 打开 Northwind.xsd 文件夹中的 App_Code/DAL “类型化数据集”,将新方法添加到 ProductsTableAdapter (右键单击并选择“ ProductsTableAdapter 添加查询) 。 这样做将打开 TableAdapter 查询配置向导,该向导将引导我们完成添加新方法的过程。 首先指示 DAL 方法将使用临时 SQL 语句。

使用临时 SQL 语句创建 DAL 方法

图 12:使用临时 SQL 语句创建 DAL 方法 (单击以查看全尺寸图像)

接下来,向导会提示我们创建哪种类型的查询。 DiscontinueAllProductsForSupplier(supplierID)由于 方法需要更新Products数据库表,因此对于指定 supplierID提供的所有产品,请将 字段设置为 Discontinued 1,我们需要创建一个用于更新数据的查询。

选择 UPDATE 查询类型

图 13:选择 UPDATE 查询类型 (单击以查看全尺寸图像)

下一个向导屏幕提供 TableAdapter 的现有 UPDATE 语句,该语句更新 DataTable 中 Products 定义的每个字段。 将此查询文本替换为以下语句:

UPDATE [Products] SET
   Discontinued = 1
WHERE SupplierID = @SupplierID

输入此查询并单击“下一步”后,最后一个向导屏幕会要求使用 新方法的名称 DiscontinueAllProductsForSupplier。 单击“完成”按钮完成向导。 返回到数据集Designer应在名为 DiscontinueAllProductsForSupplier(@SupplierID)的 中看到ProductsTableAdapter一个新方法。

将 New DAL 方法命名为 DiscontinueAllProductsForSupplier

图 14:为 New DAL 方法 DiscontinueAllProductsForSupplier 命名 (单击以查看全尺寸图像)

DiscontinueAllProductsForSupplier(supplierID)在数据访问层中创建 方法后,下一个任务是在业务逻辑层中创建 DiscontinueAllProductsForSupplier(supplierID) 方法。 为此,请打开 ProductsBLL 类文件并添加以下内容:

Public Function DiscontinueAllProductsForSupplier(supplierID As Integer) As Integer
    Return Adapter.DiscontinueAllProductsForSupplier(supplierID)
End Function

此方法只需调用 DiscontinueAllProductsForSupplier(supplierID) DAL 中的 方法,并沿提供 supplierID 的参数值传递。 如果有任何业务规则仅允许供应商在特定情况下停用产品,则应在 BLL 中在此处实施这些规则。

注意

与 类中的UpdateProductProductsBLL重载不同,DiscontinueAllProductsForSupplier(supplierID)方法签名不包含DataObjectMethodAttribute特性 (<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>) 。 这排除了 DiscontinueAllProductsForSupplier(supplierID) “更新”选项卡中 ObjectDataSource 的“配置数据源”向导下拉列表中的 方法。我省略了此属性,因为我们将直接从 ASP.NET 页中的事件处理程序调用 DiscontinueAllProductsForSupplier(supplierID) 方法。

步骤 5:向 FormView 添加停用所有产品按钮

DiscontinueAllProductsForSupplier(supplierID)完成 BLL 和 DAL 中的 方法后,添加停止所选供应商所有产品的功能的最后一步是将 Button Web 控件添加到 FormView s ItemTemplate。 让我们在供应商电话号码下方添加这样的按钮,其中包含按钮文本“停止所有产品”,属性值为 IDDiscontinueAllProductsForSupplier。 可以通过Designer添加此 Button Web 控件,方法是单击 FormView 智能标记中的“编辑模板”链接, (请参阅图 15) ,或者直接通过声明性语法添加此按钮 Web 控件。

将“所有产品”按钮 Web 控件添加到 FormView s ItemTemplate

图 15:将“所有产品”按钮 Web 控件添加到 FormView (ItemTemplate单击以查看全尺寸图像)

当访问页面的用户单击按钮时,将发出回发,并触发 FormView s ItemCommand 事件 。 若要执行自定义代码以响应此按钮被单击,我们可以为此事件创建事件处理程序。 不过,请注意, ItemCommand 只要在 FormView 中单击 任何 Button、LinkButton 或 ImageButton Web 控件,事件将触发。 这意味着,当用户在 FormView 中从一个页面移动到另一个页面时, ItemCommand 将触发事件;当用户在支持插入、更新或删除的 FormView 中单击“新建”、“编辑”或“删除”时,同样会触发事件。

ItemCommand由于 无论单击了哪个按钮都会触发,因此在事件处理程序中,我们需要一种方法来确定是否单击了“停止所有产品”按钮,或者是否是其他某个按钮。 为此,我们可以将 Button Web 控件的 CommandName 属性设置为一些标识值。 单击“按钮”时,此值 CommandName 将传递到事件处理程序中 ItemCommand ,使我们能够确定是否单击了“停止所有产品”按钮。 将“停止所有产品”按钮属性 CommandName 设置为 DiscontinueProducts 。

最后,让我们使用客户端确认对话框来确保用户确实希望停止所选供应商的产品。 正如我们在 删除时添加 Client-Side 确认 教程中看到的那样,这可以通过一些 JavaScript 来实现。 具体而言,将 Button Web 控件 OnClientClick 属性设置为 return confirm('This will mark _all_ of this supplier\'s products as discontinued. Are you certain you want to do this?');

进行这些更改后,FormView 的声明性语法应如下所示:

<asp:FormView ID="Suppliers" runat="server" DataKeyNames="SupplierID"
    DataSourceID="SuppliersDataSource" EnableViewState="False"
    AllowPaging="True">
    <ItemTemplate>
        <h3><asp:Label ID="CompanyName" runat="server"
            Text='<%# Bind("CompanyName") %>'></asp:Label></h3>
        <b>Phone:</b>
        <asp:Label ID="PhoneLabel" runat="server" Text='<%# Bind("Phone") %>' />
        <br />
        <asp:Button ID="DiscontinueAllProductsForSupplier" runat="server"
            CommandName="DiscontinueProducts" Text="Discontinue All Products"
            OnClientClick="return confirm('This will mark _all_ of this supplier\'s
                products as discontinued. Are you certain you want to do this?');" />
    </ItemTemplate>
</asp:FormView>

接下来,为 FormView 事件 ItemCommand 创建事件处理程序。 在此事件处理程序中,我们需要首先确定是否单击了“停止所有产品”按钮。 如果是这样,我们希望创建 类的 ProductsBLL 实例并调用其 DiscontinueAllProductsForSupplier(supplierID) 方法,传入 SupplierID 所选 FormView 的 :

Protected Sub Suppliers_ItemCommand(sender As Object, e As FormViewCommandEventArgs) _
    Handles Suppliers.ItemCommand
    If e.CommandName.CompareTo("DiscontinueProducts") = 0 Then
        ' The "Discontinue All Products" Button was clicked.
        ' Invoke the ProductsBLL.DiscontinueAllProductsForSupplier(supplierID) method
        ' First, get the SupplierID selected in the FormView
        Dim supplierID As Integer = CType(Suppliers.SelectedValue, Integer)
        ' Next, create an instance of the ProductsBLL class
        Dim productInfo As New ProductsBLL()
        ' Finally, invoke the DiscontinueAllProductsForSupplier(supplierID) method
        productInfo.DiscontinueAllProductsForSupplier(supplierID)
    End If
End Sub

请注意,SupplierID可以使用 FormView 的 属性访问 FormView 中当前所选供应商的 SelectedValue。 属性 SelectedValue 返回 FormView 中显示的记录的第一个数据键值。 在步骤 2 中将 ObjectDataSource 绑定到 FormView 时,Visual Studio 会自动将 FormView 属性DataKeyNames设置为 SupplierID ,该属性指示从中拉取数据键值的数据字段。

创建事件处理程序后 ItemCommand ,请花点时间测试页面。 浏览到Cocoiva de Quesos 'Las Cabras'供应商 (它是 FormView 中第五个供应商,我) 。 这家供应商提供两种产品,Queso Cabrales和Queso Manchego La Pastora,这两种产品 均未 停产。

想象一下,合作公司德奎索斯“拉斯卡布拉斯”已经停产,因此其产品将停产。 单击“停止所有产品”按钮。 这将显示客户端确认对话框, (见图 16) 。

合作组织 de Quesos Las Cabras 提供两个活性产品

图 16:合作组织 de Quesos Las Cabras 提供两个活动产品 (单击以查看全尺寸图像)

如果在客户端确认对话框中单击“确定”,表单提交将继续,导致将触发 FormView s ItemCommand 事件的回发。 然后,我们创建的事件处理程序将执行,调用 DiscontinueAllProductsForSupplier(supplierID) 方法并停用 Queso Cabrales 和 Queso Manchego La Pastora 产品。

如果禁用了 GridView 的视图状态,则每次回发时,GridView 都会反弹到基础数据存储,因此会立即更新,以反映这两种产品现已停产, (请参阅图 17) 。 但是,如果未在 GridView 中禁用视图状态,则需要在进行此更改后手动将数据重新绑定到 GridView。 为此,只需在调用 DiscontinueAllProductsForSupplier(supplierID) 方法后立即调用 GridView s DataBind() 方法。

单击“停用所有产品”按钮后,供应商的产品将相应地更新

图 17:单击“停用所有产品”按钮后,供应商的产品将相应地更新 (单击以查看全尺寸图像)

步骤 6:在业务逻辑层中创建 UpdateProduct 重载以调整产品价格

与 FormView 中的“停用所有产品”按钮一样,若要在 GridView 中添加用于提高和降低产品价格的按钮,首先需要添加适当的数据访问层和业务逻辑层方法。 由于我们已经有了更新 DAL 中单个产品行的方法,因此可以通过在 BLL 中为 UpdateProduct 方法创建新的重载来提供此类功能。

我们过去的 UpdateProduct 重载采用某些产品字段组合作为标量输入值,然后只更新了指定产品的这些字段。 对于此重载,我们将与此标准略有不同,而是传入产品和 ProductID 调整 UnitPrice (的百分比,而不是传入新的调整 UnitPrice 本身) 。 此方法将简化需要在 ASP.NET 页代码隐藏类中编写的代码,因为我们无需费心确定当前产品的 UnitPrice

UpdateProduct本教程的重载如下所示:

Public Function UpdateProduct _
    (unitPriceAdjustmentPercentage As Decimal, productID As Integer) As Boolean
    Dim products As Northwind.ProductsDataTable = Adapter.GetProductByProductID(productID)
    If products.Count = 0 Then
        ' no matching record found, return false
        Return False
    End If
    Dim product As Northwind.ProductsRow = products(0)
    ' Adjust the UnitPrice by the specified percentage (if it's not NULL)
    If Not product.IsUnitPriceNull() Then
        product.UnitPrice *= unitPriceAdjustmentPercentage
    End If
    ' Update the product record
    Dim rowsAffected As Integer = Adapter.Update(product)
    ' Return true if precisely one row was updated, otherwise false
    Return rowsAffected = 1
End Function

此重载通过 DAL s GetProductByProductID(productID) 方法检索有关指定产品的信息。 然后,它会检查是否为产品 UnitPrice 分配了数据库 NULL 值。 如果是,则价格保持不变。 但是,如果存在非NULLUnitPrice值,方法会按指定的百分比 (unitPriceAdjustmentPercent) 更新产品UnitPrice

步骤 7:将“增加”和“减少”按钮添加到 GridView

GridView (和 DetailsView) 都由字段集合组成。 除了 BoundFields、CheckBoxFields 和 TemplateFields 外,ASP.NET 还包括 ButtonField,顾名思义,它呈现为每行包含 Button、LinkButton 或 ImageButton 的列。 与 FormView 类似 ,单击 GridView 分页按钮、编辑或删除按钮、排序按钮等中的任何按钮会导致回发并引发 GridView s RowCommand 事件

ButtonField 具有一个 CommandName 属性,该属性将指定值分配给其每个 Buttons CommandName 属性。 与 FormView 一样, CommandName 事件处理程序使用 RowCommand 值来确定单击了哪个按钮。

让我们向 GridView 添加两个新的 ButtonField,一个按钮文本 Price +10%,另一个包含文本 Price -10%。 若要添加这些 ButtonField,请单击 GridView 智能标记中的“编辑列”链接,从左上角的列表中选择 ButtonField 字段类型,然后单击“添加”按钮。

向 GridView 添加两个 ButtonField

图 18:向 GridView 添加两个 ButtonField

移动两个 ButtonField,使其显示为前两个 GridView 字段。 接下来,将 Text 这两个 ButtonFields 的属性分别设置为 Price +10% 和 Price -10%,并将 CommandName 属性分别设置为 IncreasePrice 和 DecreasePrice。 默认情况下,ButtonField 将其按钮列呈现为 LinkButtons。 但是,可以通过 ButtonField 属性ButtonType更改此值。 让我们将这两个 ButtonField 呈现为常规按钮;因此,将 ButtonType 属性设置为 Button。 图 19 显示了进行这些更改后的“字段”对话框;之后是 GridView 声明性标记。

配置 ButtonFields Text、CommandName 和 ButtonType 属性

图 19:配置 ButtonFields TextCommandNameButtonType 属性

<asp:GridView ID="SuppliersProducts" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="SuppliersProductsDataSource"
    EnableViewState="False">
    <Columns>
        <asp:ButtonField ButtonType="Button" CommandName="IncreasePrice"
            Text="Price +10%" />
        <asp:ButtonField ButtonType="Button" CommandName="DecreasePrice"
            Text="Price -10%" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:C}"
            HtmlEncode="False" />
        <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
            SortExpression="Discontinued" />
    </Columns>
</asp:GridView>

创建这些 ButtonField 后,最后一步是为 GridView 事件 RowCommand 创建事件处理程序。 如果由于单击了 Price +10% 或 Price -10% 按钮而触发此事件处理程序,则需要确定 ProductID 单击按钮的行的 ,然后调用 ProductsBLL 类 s UpdateProduct 方法,同时传递相应的 UnitPrice 百分比调整以及 ProductID。 以下代码执行这些任务:

Protected Sub SuppliersProducts_RowCommand _
    (sender As Object, e As GridViewCommandEventArgs) _
        Handles SuppliersProducts.RowCommand
    If e.CommandName.CompareTo("IncreasePrice") = 0 OrElse _
       e.CommandName.CompareTo("DecreasePrice") = 0 Then
        ' The Increase Price or Decrease Price Button has been clicked
        ' Determine the ID of the product whose price was adjusted
        Dim productID As Integer = Convert.ToInt32( _
            SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)
        ' Determine how much to adjust the price
        Dim percentageAdjust As Decimal
        If e.CommandName.CompareTo("IncreasePrice") = 0 Then
            percentageAdjust = 1.1
        Else
            percentageAdjust = 0.9
        End If
        ' Adjust the price
        Dim productInfo As New ProductsBLL()
        productInfo.UpdateProduct(percentageAdjust, productID)
    End If
End Sub

若要确定 ProductID 单击了“价格 +10%”或“价格 -10%”按钮的行的 ,需要查阅 GridView 集合 DataKeys 。 此集合保存每个 GridView 行的 DataKeyNames 属性中指定的字段的值。 由于在将 ObjectDataSource 绑定到 GridView 时,Visual Studio 将 GridView 属性DataKeyNames设置为 ProductID,DataKeys(rowIndex).Value为指定的 rowIndex 提供 ProductID

ButtonField 自动传入通过 参数单击e.CommandArgument其按钮的行的 rowIndex。 因此,若要确定 ProductID 单击了“价格 +10%”或“价格 -10%”按钮的行的 ,我们使用: Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)

与“停止所有产品”按钮一样,如果禁用了 GridView 的视图状态,GridView 将在每次回发时被反弹到基础数据存储,因此将立即更新以反映通过单击任一按钮发生的价格更改。 但是,如果未在 GridView 中禁用视图状态,则需要在进行此更改后手动将数据重新绑定到 GridView。 为此,只需在调用 UpdateProduct 方法后立即调用 GridView s DataBind() 方法。

图 20 显示了查看奶奶凯利的“家园”提供的产品时的页面。 图 21 显示了在“价格 +10%”按钮已单击两次奶奶的“博森浆果分布”和“价格 -10%”按钮(对于 Northwoods Cranberry Sauce)之后的结果。

GridView 包括价格 +10% 和价格 -10% 按钮

图 20:GridView 包括价格 +10% 和价格 -10% 按钮 (单击以查看全尺寸图像)

第一个和第三个产品的价格已通过价格 +10% 和价格 -10% 按钮更新

图 21:第一个和第三个产品的价格已通过价格 +10% 和价格 -10% 按钮更新 (单击以查看全尺寸图像)

注意

GridView (和 DetailsView) 还可以将 Buttons、LinkButton 或 ImageButton 添加到其 TemplateFields。 与 BoundField 一样,单击这些按钮时,将引发回发,引发 GridView s RowCommand 事件。 但是,在 TemplateField 中添加按钮时,Button 不会 CommandArgument 像使用 ButtonFields 时那样自动设置为行的索引。 如果需要确定在事件处理程序中 RowCommand 单击的按钮的行索引,则需要使用如下代码在 TemplateField 中的声明性语法中手动设置 Button 属性 CommandArgument
<asp:Button runat="server" ... CommandArgument='<%# CType(Container, GridViewRow).RowIndex %>' />.

总结

GridView、DetailsView 和 FormView 控件都可以包括 Buttons、LinkButtons 或 ImageButtons。 单击此类按钮时,会导致回发并引发 ItemCommand FormView 和 DetailsView 控件中的 事件以及 RowCommand GridView 中的 事件。 这些数据 Web 控件具有处理常见命令相关操作(例如删除或编辑记录)的内置功能。 但是,我们也可以使用按钮,在单击时,通过执行我们自己的自定义代码来响应这些按钮。

为此,我们需要为 ItemCommandRowCommand 事件创建事件处理程序。 在此事件处理程序中,我们首先检查传入CommandName值,以确定单击了哪个按钮,然后执行相应的自定义操作。 在本教程中,我们了解了如何使用按钮和 ButtonFields 停用指定供应商的所有产品,或将特定产品的价格提高或降低 10%。

编程快乐!

关于作者

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