新增與回應 GridView 的按鈕 (C#)

作者 :Scott Mitchell

下載 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

新增自定義 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:新增 清單 供貨商的 FormView

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

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

建立名為 SuppliersDataSource 的新 ObjectDataSource

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

設定這個新的 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 清單 目前選取供應商的 CompanyName 和電話欄位

圖 7:FormView 清單 CompanyName [目前選取的供應商] 中的 和 Phone [欄位] (按兩下即可檢視完整大小的影像)

步驟 3:新增 清單 所選供應商產品的 GridView

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

建立名為 SuppliersProductsDataSource 的新 ObjectDataSource

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

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

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

圖 9:將數據源設定為使用 ProductsBLL 類別的 GetProductsBySupplierID(supplierID) 方法 (按兩下即可檢視完整大小的影像)

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

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

圖 10:指出 supplierID 參數應該來自 Suppliers FormView 控件, (按兩下即可檢視完整大小的影像)

完成 ObjectDataSource 精靈之後,GridView 將會包含每個產品數據欄位的 BoundField 或 CheckBoxField。 讓我們向下修剪,只 ProductName 顯示 和 UnitPrice BoundField 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 的按鈕時,我們會在商業規則層中叫用這個方法,並傳入選取的 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,我們需要建立更新數據的查詢。

選擇 [更新查詢類型]

圖 13:選擇 [更新查詢類型] (按兩下即可檢視完整大小的映像)

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

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

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

將新的 DAL 方法命名為 DiscontinueAllProductsForSupplier

圖 14:將新的 DAL 方法 DiscontinueAllProductsForSupplier 命名 (按兩下以檢視完整大小的影像)

DiscontinueAllProductsForSupplier(supplierID)透過在資料存取層中建立的方法,下一個工作是在商業規則層中建立 DiscontinueAllProductsForSupplier(supplierID) 方法。 若要完成此動作,請 ProductsBLL 開啟類別檔案並新增下列內容:

public int DiscontinueAllProductsForSupplier(int supplierID)
{
    return Adapter.DiscontinueAllProductsForSupplier(supplierID);
}

這個方法只會呼叫 DiscontinueAllProductsForSupplier(supplierID) DAL 中的 方法,並傳遞所提供的 supplierID 參數值。 如果有任何商務規則只允許在特定情況下停止供應商的產品,則應該在此 BLL 中實作這些規則。

注意

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

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

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

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

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

當使用者瀏覽頁面時按兩下 [按鈕],就會引發回傳並引發 FormView 的事件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 void Suppliers_ItemCommand(object sender, FormViewCommandEventArgs e)
{
    if (e.CommandName.CompareTo("DiscontinueProducts") == 0)
    {
        // The "Discontinue All Products" Button was clicked.
        // Invoke the ProductsBLL.DiscontinueAllProductsForSupplier(supplierID) method
        // First, get the SupplierID selected in the FormView
        int supplierID = (int)Suppliers.SelectedValue;
        // Next, create an instance of the ProductsBLL class
        ProductsBLL productInfo = new ProductsBLL();
        // Finally, invoke the DiscontinueAllProductsForSupplier(supplierID) method
        productInfo.DiscontinueAllProductsForSupplier(supplierID);
    }
}

請注意, SupplierID FormView 中目前選取供應商的 可以使用 FormView SelectedValue 的 屬性來存取。 屬性 SelectedValue 會傳回 FormView 中所顯示記錄的第一個數據索引鍵值。 FormView 的 DataKeyNames 屬性,指出從中提取數據索引鍵值的數據欄位,在將 ObjectDataSource 系結回步驟 2 時,Visual Studio 會自動設定 SupplierID 為 。

建立事件處理程式后 ItemCommand ,請花點時間測試頁面。 流覽至 「Quesos 』Las Cabras」 供應商 (它是 FormView for me) 的第五個供應商。 此供應商提供兩個產品 Queso Cabrales 和 Queso Manchego La Pastora,這兩個 產品都未 停止。

想像一下,一旦 'Las Cabras' 'Las Cabras' 已離開企業,因此其產品即將停止。 按兩下 [停止所有產品] 按鈕。 這會顯示用戶端確認對話框, (請參閱圖 16) 。

擷取iva de Quesos Las Cabras 提供兩個作用中產品

圖 16:在 按兩下即可檢視大小完整的影像 ()

如果您在用戶端確認對話框中按兩下 [確定],表單提交將會繼續,導致 FormView ItemCommand 事件引發回傳。 我們建立的事件處理程式接著會執行, DiscontinueAllProductsForSupplier(supplierID) 叫用 方法並停止Queso Cabrales和Queso Manchego La Pastora 產品。

如果您已停用 GridView 的檢視狀態,GridView 會在每個回傳上重新系結至基礎數據存放區,因此會立即更新,以反映這兩個產品現在已停止 (請參閱圖 17) 。 不過,如果您尚未停用 GridView 中的檢視狀態,您必須在進行這項變更之後,手動將數據重新系結至 GridView。 若要達成此目的,只要在叫DiscontinueAllProductsForSupplier(supplierID)用 方法之後立即呼叫 GridView DataBind() 的 方法即可。

按兩下 [停止所有產品] 按鈕之後,供應商的產品會據以更新

圖 17:按兩下 [停止所有產品] 按鈕之後,供貨商的產品會據以更新 (按兩下以檢視大小完整的影像)

步驟 6:在商業規則層中建立 UpdateProduct 多載以調整產品的價格

如同 FormView 中的 [停止所有產品] 按鈕,為了新增按鈕來增加和減少 GridView 中產品的價格,我們必須先新增適當的數據存取層和商業規則層方法。 由於我們已經有一個在 DAL 中更新單一產品數據列的方法,因此我們可以在 BLL 中為 UpdateProduct 方法建立新的多載,以提供這類功能。

過去的 UpdateProduct 多載已採用一些產品欄位組合做為純量輸入值,然後只更新指定產品的那些字段。 在此多載中,我們將與此標準稍有不同,而是傳入產品的 ProductID 和 要調整 UnitPrice (的百分比,而不是傳入新的、調整 UnitPrice 本身) 。 這種方法可簡化我們在 ASP.NET 頁程式代碼後置類別中撰寫的程式代碼,因為我們不需要同時判斷目前產品的 UnitPrice

UpdateProduct本教學課程的多載如下所示:

public bool UpdateProduct(decimal unitPriceAdjustmentPercentage, int productID)
{
    Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
    if (products.Count == 0)
        // no matching record found, return false
        return false;
    Northwind.ProductsRow product = products[0];
    // Adjust the UnitPrice by the specified percentage (if it's not NULL)
    if (!product.IsUnitPriceNull())
        product.UnitPrice *= unitPriceAdjustmentPercentage;
    // Update the product record
    int rowsAffected = Adapter.Update(product);
    // Return true if precisely one row was updated, otherwise false
    return rowsAffected == 1;
}

此多載會透過 DAL 的 GetProductByProductID(productID) 方法來擷取指定產品的相關信息。 然後,它會檢查產品是否已 UnitPrice 指派資料庫 NULL 值。 如果是,則價格會保持不變。 不過,如果有非NULLUnitPrice 值,則方法會依指定的百分比更新產品的 UnitPrice (unitPriceAdjustmentPercent) 。

步驟 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

移動兩個 ButtonFields,使其顯示為前兩個 GridView 字段。 接下來,將這兩個 ButtonFields 的屬性分別設定 Text 為 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 叫用類別 UpdateProduct 的 方法,並傳遞適當的 UnitPrice 百分比調整以及 ProductID。 下列程式代碼會執行下列工作:

protected void SuppliersProducts_RowCommand(object sender, GridViewCommandEventArgs e)
{
    if (e.CommandName.CompareTo("IncreasePrice") == 0 ||
        e.CommandName.CompareTo("DecreasePrice") == 0)
    {
        // The Increase Price or Decrease Price Button has been clicked
        // Determine the ID of the product whose price was adjusted
        int productID =
            (int)SuppliersProducts.DataKeys[Convert.ToInt32(e.CommandArgument)].Value;
        // Determine how much to adjust the price
        decimal percentageAdjust;
        if (e.CommandName.CompareTo("IncreasePrice") == 0)
            percentageAdjust = 1.1M;
        else
            percentageAdjust = 0.9M;

        // Adjust the price
        ProductsBLL productInfo = new ProductsBLL();
        productInfo.UpdateProduct(percentageAdjust, productID);
    }
}

若要判斷 ProductID 按下 Price +10% 或 Price -10% 按鈕之數據列的 ,我們需要查閱 GridView 的 DataKeys 集合。 此集合會保存每個 GridView 資料列之 DataKeyNames 屬性中指定的欄位值。 由於 GridView 的 DataKeyNames 屬性在將 ObjectDataSource 系結至 GridView 時已設定為 ProductID,因此會 DataKeys(rowIndex).Value 提供 ProductID 指定 之 rowIndex 的 。

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

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

圖 20 顯示檢視 Grandma Kelly 所提供產品時的頁面。 圖 21 顯示 [價格 + 10%] 按鈕之後的結果,已針對 Grandma 的[樹葉分佈] 按兩次,而 [價格 ] -10% 按鈕一次用於 Northwoods Cranberry Sauce。

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

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

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

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

注意

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

摘要

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

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

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET