共用方式為


新增與回應 GridView 的按鈕 (VB)

由斯科特· 米切爾

下載 PDF

在本教學課程中,我們將探討如何將自定義按鈕新增至範本和 GridView 或 DetailsView 控件的欄位。 特別是,我們將建置具有 FormView 的介面,可讓使用者逐頁流覽供應商。

簡介

雖然許多報告案例牽涉到報表數據的只讀存取,但報表並不罕見地包含根據所顯示數據執行動作的能力。 這通常涉及新增 Button、LinkButton 或 ImageButton Web 控制件,其中每個記錄都會顯示在報表中,當按下時,會導致回傳並叫用某些伺服器端程式代碼。 根據記錄來編輯和刪除資料是最常見的範例。 事實上,正如我們從插入、更新和刪除數據概觀開始,編輯和刪除數據教學課程非常常見,因此 GridView、DetailsView 和 FormView 控件可以支援這類功能,而不需要撰寫單一程序代碼。

除了 [編輯和刪除] 按鈕之外,GridView、DetailsView 和 FormView 控件也可以包含 Buttons、LinkButtons 或 ImageButtons,按兩下時會執行一些自定義伺服器端邏輯。 在本教學課程中,我們將探討如何將自定義按鈕新增至範本和 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

新增自定義按鈕相關教學課程的 ASP.NET 頁面

圖 2:新增自定義按鈕相關教學課程的 ASP.NET 頁面

就像在其他資料夾中一樣, Default.aspx 資料夾中 CustomButtons 會列出其區段中的教學課程。 回想一下, SectionLevelTutorialListing.ascx 使用者控件會提供這項功能。 因此,將這個使用者控制件Default.aspx從 方案總管 拖曳至頁面的設計檢視,以將它新增至 。

將 SectionLevelTutorialListing.ascx 使用者控件新增至 Default.aspx

圖 3:將使用者控制項新增 SectionLevelTutorialListing.ascxDefault.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:新增列出供應商的 FormView

讓我們透過新增列出供應商的 FormView 來開始使用本教學課程。 如簡介中所述,此 FormView 可讓使用者逐頁流覽供應商,並在 GridView 中顯示供應商所提供的產品。 此外,此 FormView 會包含按鈕,當按兩下時,會將所有供應商的產品標示為已停止。 在我們擔心將自定義按鈕新增至 FormView 之前,讓我們先建立 FormView,讓它顯示供貨商資訊。

從開啟 CustomButtons.aspx 資料夾中的頁面 CustomButtons 開始。 將 FormView 從工具箱拖曳至設計工具,並將其屬性Suppliers設定為 ,以將 FormView ID 新增至頁面。 從 FormView 的智慧標記中,選擇建立名為 SuppliersDataSource的新 ObjectDataSource。

建立名為 SuppliersDataSource 的新 ObjectDataSource

圖 5:建立名為 SuppliersDataSource 的新 ObjectDataSource (按兩下以檢視完整大小的影像

設定這個新的 ObjectDataSource,使其從 SuppliersBLL 類別 s GetSuppliers() 方法進行查詢(請參閱圖 6)。 由於此 FormView 不提供更新供應商資訊的介面,請從 [更新] 索引標籤的下拉式清單中選取 [無] 選項。

設定數據源以使用 SuppliersBLL 類別 s GetSuppliers() 方法

圖 6:設定資料來源以使用 SuppliersBLL 類別 s GetSuppliers() 方法 (按兩下以檢視完整大小的影像

設定 ObjectDataSource 之後,Visual Studio 會產生 InsertItemTemplateFormView 的 、 EditItemTemplateItemTemplateInsertItemTemplate拿掉 並EditItemTemplate修改 ,ItemTemplate使其只顯示供應商的公司名稱和電話號碼。 最後,從其智慧標記中核取 [啟用分頁] 複選框,或將其 屬性設定 AllowPagingTrue,以開啟 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 會從目前選取的供應商列出 CompanyName 和電話欄位

圖 7:FormView 列出 CompanyName 目前選取供貨商的 和 Phone 欄位 (按兩下以檢視完整大小的影像

步驟 3:新增列出所選供應商產品的 GridView

在我們將 [停止所有產品] 按鈕新增至 FormView 範本之前,讓我們先在 FormView 下方新增 GridView,以列出所選供貨商所提供的產品。 若要達成此目的,請將 GridView 新增至頁面、將其 ID 屬性設定為 SuppliersProducts,然後新增名為 SuppliersProductsDataSource的新 ObjectDataSource。

建立名為 SuppliersProductsDataSource 的新 ObjectDataSource

圖 8:建立名為 SuppliersProductsDataSource 的新 ObjectDataSource (按兩下以檢視完整大小的影像

將此 ObjectDataSource 設定為使用 ProductsBLL 類別 s GetProductsBySupplierID(supplierID) 方法(請參閱圖 9)。 雖然此 GridView 允許調整產品的價格,但不會使用 GridView 中的內建編輯或刪除功能。 因此,我們可以將 ObjectDataSource 的 UPDATE、INSERT 和 DELETE 索引標籤標的下拉式清單設定為 [無]。

將數據源設定為使用 ProductsBLL 類別 s GetProductsBySupplierID(supplierID) 方法

圖 9:設定資料來源以使用 ProductsBLL 類別 s GetProductsBySupplierID(supplierID) 方法 (按兩下以檢視完整大小的影像

GetProductsBySupplierID(supplierID)由於 方法接受輸入參數,因此 ObjectDataSource 精靈會提示我們輸入此參數值的來源。 若要從 FormView 傳入 SupplierID 值,請將 [參數來源] 下拉式清單設定為 Control,並將 ControlID 下拉式清單設定為 Suppliers (步驟 2 中建立的 FormView 標識符)。

指出 supplierID 參數應該來自供應商 FormView 控件

圖 10:指出 supplierID 參數應來自 Suppliers FormView 控件 (按一下以檢視完整大小的影像

完成 ObjectDataSource 精靈之後,GridView 會針對每個產品的數據欄位包含 BoundField 或 CheckBoxField。 讓我們修剪這個,只 ProductName 顯示 和 BoundFields 以及 UnitPrice 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 選取東京 Traders 供應商時此頁面的螢幕快照。

選取的供應商產品會顯示在 GridView 中

圖 11:選取的供應商產品會顯示在 GridView 中(按兩下以檢視完整大小的影像

步驟 4:建立 DAL 和 BLL 方法以中止供應商的所有產品

在我們可以將 Button 新增至 FormView 之前,按兩下時停止所有供應商的產品,我們必須先將方法新增至執行此動作的 DAL 和 BLL。 特別是,這個方法會命名為 DiscontinueAllProductsForSupplier(supplierID)。 按兩下 FormView 的按鈕時,我們會在商業規則層中叫用此方法,並傳入選取的供應商 s 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:選擇 [更新查詢類型] (按兩下以檢視完整大小的影像

下一個精靈畫面會提供 TableAdapter 的現有 UPDATE 語句,以更新 DataTable 中 Products 定義的每個欄位。 以下欄語句取代此查詢文字:

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

輸入此查詢並按兩下一步之後,最後一個精靈畫面會要求使用新的方法名稱 DiscontinueAllProductsForSupplier。 按兩下 [完成] 按鈕來完成精靈。 返回 DataSet 設計工具時,您應該會在名為 DiscontinueAllProductsForSupplier(@SupplierID)ProductsTableAdapter 中看到新的方法。

將新的 DAL 方法命名為 DiscontinueAllProductsForSupplier

圖 14:命名新的 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 中實作這些規則。

注意

UpdateProduct與類別中的ProductsBLL多載不同,DiscontinueAllProductsForSupplier(supplierID)方法簽章不包含 DataObjectMethodAttribute 屬性 (<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>)。 這排除 DiscontinueAllProductsForSupplier(supplierID) 了 [UPDATE] 索引標籤中 ObjectDataSource s [設定數據源精靈] 下拉式清單中的 方法。我省略了此屬性,因為我們會直接從 ASP.NET 頁面中的事件處理程式呼叫 DiscontinueAllProductsForSupplier(supplierID) 方法。

步驟 5:將 [停止所有產品] 按鈕新增至 FormView

DiscontinueAllProductsForSupplier(supplierID)在 BLL 和 DAL 中完成方法之後,新增停止所選供貨商所有產品的能力的最後一個步驟是將 Button Web 控件新增至 FormView s ItemTemplate。 讓我們在供應商的電話號碼下方新增這類按鈕,其中包含按鈕文字、[中止所有產品] 和 ID 的屬性值 DiscontinueAllProductsForSupplier。 您可以透過設計工具新增此 Button Web 控件,方法是單擊 FormView 智慧標記中的 [編輯範本] 連結(請參閱圖 15),或直接透過宣告式語法。

將停止所有產品按鈕 Web 控件新增至 FormView s ItemTemplate

圖 15:將 [停止所有產品] 按鈕 Web 控件新增至 FormView s ItemTemplate按兩下以檢視完整大小的影像

當使用者瀏覽頁面時按下 Button,就會發生回傳,並引發 FormView 事件ItemCommand。 若要執行自定義程式代碼以回應所按下的按鈕,我們可以為此事件建立事件處理程式。 不過,ItemCommand瞭解每當在 FormView 內按兩下任何 Button、LinkButton 或 ImageButton Web 控制件時,就會引發事件。 這表示當使用者在 FormView 中從一個頁面移到另一個頁面時, ItemCommand 就會引發事件;當使用者在支援插入、更新或刪除的 FormView 中按兩下 [新增]、[編輯] 或 [刪除] 時,就會發生相同事件。

ItemCommand因為不論按下哪個按鈕都會引發,因此在事件處理程式中,我們需要一種方式來判斷是否按下 [停止所有產品] 按鈕,或是否為其他按鈕。 若要達成此目的,我們可以將 Button Web 控件 的 CommandName 屬性設定為一些識別值。 按兩下 [按鈕] 時,這個 CommandName 值會傳遞至 ItemCommand 事件處理程式,讓我們判斷 [停止所有產品] 按鈕是否為按下按鈕。 將 [中止所有產品] 按鈕的 CommandName 屬性設定為 DiscontinueProducts 。

最後,讓我們使用用戶端確認對話方塊,以確保使用者真的想要停止選取的供應商產品。 如我們在刪除時新增用戶端確認教學課程中所見,這可以使用一些 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 s 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 中所顯示記錄的第一個數據索引鍵值。 FormView s DataKeyNames 屬性,表示從中提取數據索引鍵值的數據欄位,在將 ObjectDataSource 系結回步驟 2 時,Visual Studio 會自動設定 SupplierID 為 。

建立事件處理程式后 ItemCommand ,請花點時間測試頁面。 流覽至Cocoiva de Quesos 'Las Cabras' 供貨商(這是我 FormView 中的第五個供應商)。 此供應商提供兩種產品:Queso Cabrales 和 Queso Manchego La Pastora,兩 者均未 停產。

想像一下,合作iva de Quesos “Las Cabras” 已經走出企業,因此其產品將被停止。 按兩下 [停止所有產品] 按鈕。 這會顯示客戶端確認對話方塊(請參閱圖 16)。

Partneriva de Quesos Las Cabras 供應兩種有效產品

圖 16:P artneriva de Quesos Las Cabras 供應兩種使用中產品 (按兩下以檢視全尺寸影像

如果您在用戶端確認對話框中按兩下 [確定],表單提交將會繼續,導致 FormView 事件 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以及調整的百分比(而不是傳入新的、調整UnitPriceUnitPrice本身)。 這種方法可簡化我們需要在 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 方法 GetProductByProductID(productID) 擷取指定產品的相關信息。 然後,它會檢查產品 UnitPrice 是否已指派資料庫 NULL 值。 如果是,價格會保持不變。 不過,如果有非NULLUnitPrice值,則方法會依指定的百分比來更新產品 UnitPriceunitPriceAdjustmentPercent

步驟 7:將增加和減少按鈕新增至 GridView

GridView (和 DetailsView) 都是由字段集合所組成。 除了 BoundFields、CheckBoxFields 和 TemplateFields 之外,ASP.NET 還包含 ButtonField,如其名稱所示,會轉譯為每個數據列具有 Button、LinkButton 或 ImageButton 的數據行。 與 FormView 類似,按下 GridView 分頁按鈕、編輯或刪除按鈕、排序按鈕等中的任何按鈕會導致回傳並引發 GridView 事件RowCommand

ButtonField 有一個 CommandName 屬性,會將指定的值指派給其每個 Buttons CommandName 屬性。 和 FormView 一樣, CommandName 事件處理程式會使用 RowCommand 值來判斷按下哪個按鈕。

讓我們將兩個新的 ButtonFields 新增至 GridView,一個是按鈕文字 Price +10%,另一個是文字 Price -10%。 若要新增這些 ButtonFields,請按下 GridView 智慧標記中的 [編輯資料行] 連結,從左上方的清單選取 ButtonField 欄位類型,然後按兩下 [新增] 按鈕。

將兩個 ButtonFields 新增至 GridView

圖 18:將兩個 ButtonFields 新增至 GridView

移動兩個 ButtonField,使其顯示為前兩個 GridView 字段。 接下來,將 Text 這兩個 ButtonField 的屬性分別設定為 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>

建立這些 ButtonFields 後,最後一個步驟是建立 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 按下 Price +10% 或 Price -10% 按鈕之數據列的 ,我們需要查閱 GridView 集合 DataKeys 。 此集合會保存每個 GridView 資料列之 屬性中指定的 DataKeyNames 欄位值。 由於將 ObjectDataSource 系結至 GridView 時,GridView 的 DataKeyNames 屬性已設定為 Visual Studio 的 ProductID, DataKeys(rowIndex).Value 因此會提供 ProductID 指定 rowIndex 的 。

ButtonField 會自動傳入已透過 e.CommandArgument 參數按鍵之數據列的 rowIndex。 因此,若要判斷 ProductID 按下 Price +10% 或 Price -10% 按鈕之數據列的 ,我們使用: Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)

如同 [停止所有產品] 按鈕,如果您已停用 GridView 的檢視狀態,GridView 會在每個回傳時重新系結至基礎數據存放區,因此會立即更新,以反映從按兩下任一按鈕所發生的價格變更。 不過,如果您尚未在 GridView 中停用檢視狀態,在進行這項變更之後,您必須手動將數據重新繫結至 GridView。 若要達成此目的,只要在叫用 方法之後UpdateProduct立即呼叫 GridView s DataBind() 方法即可。

圖 20 顯示檢視奶奶凱利之家所提供的產品時的頁面。 圖 21 顯示價格 +10% 按鈕之後的結果已針對奶奶的 Boysenberry Spread 單擊兩次,而 Northwoods Cranberry Sauce 的 Price -10% 按鈕一次。

GridView 包含價格 +10% 和價格 -10% 按鈕

圖 20:GridView 包含價格 +10% 和價格 -10% 按鈕(按兩下以檢視完整大小的影像

第一個和第三個產品的價格已透過價格 +10% 和價格 -10% 按鈕更新

圖 21:第一個和第三個產品的價格已透過價格 +10% 和價格 -10% 按鈕更新 (按兩下以檢視完整大小的影像

注意

GridView (和 DetailsView) 也可以將 Buttons、LinkButtons 或 ImageButtons 新增至其 TemplateFields。 如同 BoundField,這些按鈕在按兩下時會引發回傳,引發 GridView s RowCommand 事件。 不過,在 TemplateField 中新增按鈕時,Button s CommandArgument 不會在使用 ButtonFields 時自動設定為數據列的索引。 如果您需要判斷事件處理程式內 RowCommand 所按下按鈕的數據列索引,您必須使用類似下列程序代碼,在 TemplateField 的宣告式語法中手動設定 Button 屬性 CommandArgument
<asp:Button runat="server" ... CommandArgument='<%# CType(Container, GridViewRow).RowIndex %>' />.

摘要

GridView、DetailsView 和 FormView 控件全都可以包含 Buttons、LinkButtons 或 ImageButtons。 按兩下時,這類按鈕會導致回傳,並在 FormView 和 DetailsView 控制件中引發 ItemCommand 事件,以及 RowCommand GridView 中的事件。 這些數據 Web 控制件具有內建功能,可處理常見的命令相關動作,例如刪除或編輯記錄。 不過,我們也可以使用按兩下時回應執行我們自己的自定義程式碼的按鈕。

若要達成此目的,我們需要建立 ItemCommandRowCommand 事件的事件處理程式。 在此事件處理程式中,我們會先檢查傳入 CommandName 值,以判斷已按下哪個按鈕,然後採取適當的自定義動作。 在本教學課程中,我們已瞭解如何使用按鈕和 ButtonFields 來停止指定供應商的所有產品,或將特定產品的價格提高或降低 10%。

快樂的程序設計!

關於作者

斯科特·米切爾,七本 ASP/ASP.NET 書籍和 4GuysFromRolla.com 創始人的作者,自1998年以來一直與Microsoft Web 技術合作。 斯科特擔任獨立顧問、教練和作家。 他的最新書是 山姆斯在24小時內 ASP.NET 2.0。 他可以到達 mitchell@4GuysFromRolla.com, 或通過他的博客,可以在 找到 http://ScottOnWriting.NET