GridView にボタンを追加し、応答する (VB)
このチュートリアルでは、テンプレートに対してと GridView または DetailsView コントロールのフィールドに対してカスタム ボタンを追加する方法について説明します。 具体的には、FormView (ユーザーがサプライヤーごとのページを表示できる) があるインターフェイスを構築します。
はじめに
多くのレポート シナリオにはレポート データへの読み取り専用アクセスが含まれますが、レポートに、表示されるデータに基づいてアクションを実行する機能を含めることは珍しくありません。 一般的に、このためには、レポート内に表示される各レコードに Button、LinkButton、または ImageButton Web コントロールを追加し、クリックするとポストバックが発生してサーバー側のコードが呼び出されるようにします。 レコードごとのデータの編集と削除が最も一般的な例です。 実際に、「データの挿入、更新、削除の概要」チュートリアルから説明してきたように、編集と削除は一般的であり、コードを 1 行も記述せずに GridView、DetailsView、FormView コントロールでこのような機能をサポートできます。
GridView、DetailsView、FormView コントロールには、編集および削除ボタンに加え、クリックするとカスタムのサーバー側ロジックが実行される Button、LinkButton、ImageButton を含めることもできます。 このチュートリアルでは、テンプレートに対してと GridView または DetailsView コントロールのフィールドに対してカスタム ボタンを追加する方法について説明します。 具体的には、FormView (ユーザーがサプライヤーごとのページを表示できる) があるインターフェイスを構築します。 指定されたサプライヤーについて、FormView に、そのサプライヤーに関する情報と、クリックするとその関連するすべての製品が廃止としてマークされる Button Web コントロールが表示されます。 また、GridView に、選択したサプライヤーが提供している製品が一覧表示され、各行に値上げおよび値下げボタン (クリックするとその製品の UnitPrice
が 10% ずつ値上げまたは値下げされる) が表示されます。 (図 1 を参照)。
図 1: FormView と GridView の両方に、カスタム アクションを実行するボタンが含まれている (クリックするとフルサイズの画像が表示されます)
手順 1: ボタン チュートリアルの Web ページを追加する
カスタム ボタンを追加する方法を説明する前に、まず、このチュートリアルに必要な ASP.NET ページを Web サイト プロジェクトで作成しましょう。 まず、CustomButtons
という名前の新しいフォルダーを追加します。 次に、そのフォルダーに次の 2 つの ASP.NET ページを追加し、必ず各ページを Site.master
マスター ページに関連付けます:
Default.aspx
CustomButtons.aspx
図 2: カスタム ボタン関連のチュートリアルの ASP.NET ページを追加する
他のフォルダーと同様に、CustomButtons
フォルダーの 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
を更新した後、ブラウザーでチュートリアル Web サイトの表示を確認してみましょう。 左側のメニューに、チュートリアルの編集、挿入、削除の項目が含まれるようになりました。
図 4: サイト マップにカスタム ボタン チュートリアルのエントリが含まれるようになった
手順 2: サプライヤーを一覧表示する FormView を追加する
このチュートリアルでは、まず、サプライヤーを一覧表示する FormView を追加しましょう。 「はじめに」で説明したように、この FormView では、ユーザーがサプライヤーごとのページを表示でき、そのサプライヤーが提供している製品が GridView で表示されます。 また、この FormView には、クリックするとすべてのサプライヤーの製品が廃止としてマークされるボタンが含まれます。 FormView へのカスタム ボタンの追加に取り掛かる前に、まず、サプライヤー情報が表示されるように FormView を作成しましょう。
まず、CustomButtons
フォルダーの CustomButtons.aspx
ページを開きます。 FormView をツールボックスからデザイナーにドラッグしてページに追加し、その ID
プロパティを Suppliers
に設定します。 FormView のスマート タグで、SuppliersDataSource
という名前の新しい ObjectDataSource を作成することにします。
図 5: SuppliersDataSource
という名前の新しい ObjectDataSource を作成します (クリックするとフルサイズの画像が表示されます)
SuppliersBLL
クラスの GetSuppliers()
メソッドからクエリを実行するように、この新しい ObjectDataSource を構成します (図 6 を参照)。 この FormView ではサプライヤー情報を更新するためのインターフェイスを提供しないため、[UPDATE] タブ内のドロップダウン リストから [(なし)] オプションを選択します。
図 6: SuppliersBLL
クラスの GetSuppliers()
メソッドを使うようにデータ ソースを構成する (クリックするとフルサイズの画像が表示されます)
ObjectDataSource を構成すると、Visual Studio で、その FormView 用の InsertItemTemplate
、EditItemTemplate
、ItemTemplate
が生成されます。 InsertItemTemplate
と EditItemTemplate
を削除し、サプライヤーの会社名と電話番号のみが表示されるように ItemTemplate
を変更します。 最後に、FormView でのページングのサポートを、そのスマート タグで [ページングを有効にする] チェック ボックスを選択して (または、その AllowPaging
プロパティを True
に設定して) 有効にします。 これらの変更の後の、GridView の宣言型マークアップは次のようになります:
<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 ページを示します。
図 7: 現在選択しているサプライヤーの CompanyName
および Phone
フィールドが FormView で表示される (クリックするとフルサイズの画像が表示されます)
手順 3: 選択されたサプライヤーの製品を一覧表示する GridView を追加する
FormView のテンプレートに [Discontinue All Products] (すべての製品を廃止) ボタンを追加する前に、まず、選択されたサプライヤーから提供されている製品を一覧表示する GridView を FormView の下に追加します。 これを実現するには、GridView をページに追加し、その ID
プロパティを SuppliersProducts
に設定し、SuppliersProductsDataSource
という名前の新しい ObjectDataSource を追加します。
図 8: SuppliersProductsDataSource
という名前の新しい ObjectDataSource を作成する (クリックするとフルサイズの画像が表示されます)
ProductsBLL クラスの GetProductsBySupplierID(supplierID)
メソッドを使うようにこの ObjectDataSource を構成します (図 9 を参照)。 この GridView では製品の価格を調整できますが、GridView に組み込まれている編集および削除機能は使いません。 そのため、ObjectDataSource の [UPDATE]、[INSERT]、[DELETE] タブのドロップダウン リストを [(なし)] に設定します。
図 9: ProductsBLL
クラスの GetProductsBySupplierID(supplierID)
メソッドを使うようにデータ ソースを構成する (クリックするとフルサイズの画像が表示されます)
GetProductsBySupplierID(supplierID)
メソッドは入力パラメーターを受け取るため、ObjectDataSource ウィザードで、このパラメーター値のソースを入力するよう求められます。 FormView から SupplierID
値を渡すには、[パラメーター ソース] ドロップダウン リストを [コントロール] に、[ControlID] ドロップダウン リストを Suppliers
(手順 2 で作成した FormView の ID) に設定します。
図 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 からサプライヤー Tokyo Traders を選択したときのこのページのスクリーン ショットを示します。
図 11: 選択したサプライヤーの製品が GridView に表示される (クリックするとフルサイズの画像が表示されます)
手順 4: サプライヤーのすべての製品を廃止にするための DAL および BLL メソッドを作成する
クリックするとそのサプライヤーの製品すべてが廃止になるボタンを FormView に追加する前に、まず、このアクションを実行するメソッドを DAL と BLL に追加する必要があります。 具体的に述べると、このメソッドには DiscontinueAllProductsForSupplier(supplierID)
という名前を付けます。 FormView のボタンをクリックすると、ビジネス ロジック層 (BLL) でこのメソッドが呼び出されて、選択したサプライヤーの SupplierID
が渡されます。その後、BLL で、対応するデータ アクセス層 (DAL) のメソッドが呼び出されます。これにより、指定されたサプライヤーの製品を廃止にする UPDATE
ステートメントがデータベースに対して発行されます。
前のチュートリアルと同様に、ボトムアップ アプローチを使い、まず DAL メソッドを作成し、次に BLL メソッドを作成し、最後に ASP.NET ページで機能を実装します。 App_Code/DAL
フォルダー内の型指定された DataSet Northwind.xsd
を開き、新しいメソッドを ProductsTableAdapter
に追加します (ProductsTableAdapter
を右クリックし、[クエリの追加] を選択する)。 これにより、新しいメソッドを追加するプロセスを示す TableAdapter クエリ構成ウィザードが起動されます。 まず、DAL メソッドでアドホック SQL ステートメントを使うことを指定します。
図 12: アドホック SQL ステートメントを使って DAL メソッドを作成する (クリックするとフルサイズの画像が表示されます)
次に、ウィザードで、作成するクエリの種類を確認されます。 DiscontinueAllProductsForSupplier(supplierID)
メソッドでは、Products
データベース テーブルを更新して、指定された supplierID
で提供されているすべての製品について Discontinued
フィールドを 1 に設定する必要があります。そのため、データを更新するクエリを作成する必要があります。
図 13: クエリの種類として UPDATE を選択する (クリックするとフルサイズの画像が表示されます)
次のウィザード画面では、Products
DataTable で定義されている各フィールドを更新する、TableAdapter の既存の UPDATE
ステートメントが提供されます。 このクエリ テキストを次のステートメントに置き換えます:
UPDATE [Products] SET
Discontinued = 1
WHERE SupplierID = @SupplierID
このクエリを入力し、[次へ] をクリックすると、最後のウィザード画面で、その新しいメソッドの名前に DiscontinueAllProductsForSupplier
を使うかどうかを確認されます。 [完了] ボタンをクリックしてウィザードを完了します。 データセット デザイナーに戻ると、ProductsTableAdapter
内に DiscontinueAllProductsForSupplier(@SupplierID)
という名前の新しいメソッドがあります。
図 14: 新しい DAL メソッドに DiscontinueAllProductsForSupplier
という名前を付ける (クリックするとフルサイズの画像が表示されます)
データ アクセス層で DiscontinueAllProductsForSupplier(supplierID)
メソッドを作成したので、次のタスクは、ビジネス ロジック層での DiscontinueAllProductsForSupplier(supplierID)
メソッドの作成です。 これを実現するには、ProductsBLL
クラス ファイルを開き、次の内容を追加します:
Public Function DiscontinueAllProductsForSupplier(supplierID As Integer) As Integer
Return Adapter.DiscontinueAllProductsForSupplier(supplierID)
End Function
このメソッドでは、DAL 内の DiscontinueAllProductsForSupplier(supplierID)
メソッドが呼び出されて、指定した supplierID
パラメーター値が渡されるだけです。 特定の状況下でのみサプライヤーの製品を廃止できるようにするビジネス ルールがあった場合は、BLL において、ここでそれらのルールを実装する必要があります。
Note
ProductsBLL
クラス内の UpdateProduct
オーバーロードとは異なり、DiscontinueAllProductsForSupplier(supplierID)
メソッドのシグネチャには DataObjectMethodAttribute
属性 (<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, Boolean)>
) は含まれません。 これにより、ObjectDataSource のデータ ソース構成ウィザードの [UPDATE] タブにあるドロップダウン リストから DiscontinueAllProductsForSupplier(supplierID)
メソッドが除外されます。この ASP.NET ページではイベント ハンドラーから DiscontinueAllProductsForSupplier(supplierID)
メソッドを直接呼び出すため、この属性を省略しました。
手順 5: FormView に [Discontinue All Products] (すべての製品を廃止) ボタンを追加する
BLL と DAL での DiscontinueAllProductsForSupplier(supplierID)
メソッドが完成したので、選択されたサプライヤーのすべての製品を廃止にする機能を追加するための最後の手順は、FormView の ItemTemplate
への Button Web コントロールの追加です。 そのようなボタンを、ボタン テキストを [Discontinue All Products] (すべての製品を廃止) にし ID
プロパティの値を DiscontinueAllProductsForSupplier
にしてサプライヤーの電話番号の下に追加しましょう。 この Button Web コントロールは、デザイナーで FormView のスマート タグ (図 15 を参照) にある [テンプレートの編集] リンクをクリックして追加するか、宣言構文で直接追加することができます。
図 15: FormView の ItemTemplate
に [Discontinue All Products] (すべての製品を廃止) Button Web コントロールを追加する (クリックするとフルサイズの画像が表示されます)
ページにアクセスしているユーザーがこのボタンをクリックすると、ポストバックが発生し、FormView の ItemCommand
イベント が発生します。 このボタンのクリックに応答してカスタム コードを実行するには、このイベントのイベント ハンドラーを作成します。 ただし、FormView 内で Button、LinkButton、ImageButton Web コントロールのどれかがクリックされるたびに ItemCommand
イベントが発生することを理解しておいてください。 つまり、ユーザーが FormView 内のあるページから別のページに移動すると ItemCommand
イベントが発生するということです。挿入、更新、または削除をサポートする FormView 内で [New] (新規)、[Edit] (編集)、または [Delete] (削除) をクリックしたときも同様です。
クリックされたボタンに関係なく ItemCommand
が発生するため、イベント ハンドラーでは、クリックされたのが [Discontinue All Products] (すべての製品を廃止) ボタンだったか他のボタンだったかを判断する方法が必要です。 これを実現するために、Button Web コントロールの CommandName
プロパティを特定の値に設定できます。 ボタンがクリックされると、この CommandName
値が ItemCommand
イベント ハンドラーに渡されます。それにより、クリックされたのが [Discontinue All Products] (すべての製品を廃止) ボタンであるかどうかを判断できるようになります。 [Discontinue All Products] (すべての製品を廃止) ボタンの 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 の ItemCommand
イベントのイベント ハンドラーを作成します。 このイベント ハンドラーでは、まず、[Discontinue All Products] (すべての製品を廃止) ボタンがクリックされたかどうかを判断する必要があります。 その場合は、ProductsBLL
クラスのインスタンスを作成し、その DiscontinueAllProductsForSupplier(supplierID)
メソッドを呼び出して、選択された FormView の SupplierID
を渡します:
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
FormView 内の現在選択されているサプライヤーの SupplierID
に FormView の SelectedValue
プロパティを使ってアクセスできることに注目してください。 SelectedValue
プロパティでは、FormView で表示されているレコードの最初のデータ キー値が返されます。 FormView の DataKeyNames
プロパティ (データ キー値の取得元のデータ フィールドを示す) は、手順 2 で ObjectDataSource を FormView にバインドしたときに、Visual Studio によって自動的に SupplierID
に設定されています。
ItemCommand
イベント ハンドラーを作成したので、このページをテストします。 サプライヤー Cooperativa de Quesos 'Las Cabras' (FormView 内の 5 番目のサプライヤー) を閲覧します。 このサプライヤーは、Queso Cabrales と Queso Manchego La Pastora という 2 つの製品を提供しており、それらは両方とも廃止になっていません。
たとえば、Cooperativa de Quesos 'Las Cabras' が廃業したためその製品を廃止にするとします。 [Discontinue All Products] (すべての製品を廃止) ボタンをクリックします。 これにより、クライアント側の確認ダイアログ ボックスが表示されます (図 16 を参照)。
図 16: Cooperativa de Quesos Las Cabras はアクティブな製品を 2 つ供給している (クリックするとフルサイズの画像が表示されます)
クライアント側の確認ダイアログ ボックスで [OK] をクリックすると、フォームの送信が開始されて、ポストバックが発生し、それにより FormView の ItemCommand
イベントが発生します。 次に、作成したイベント ハンドラーが実行されて、DiscontinueAllProductsForSupplier(supplierID)
メソッドが呼び出され、Queso Cabrales と Queso Manchego La Pastora という製品両方が廃止になります。
GridView のビュー状態を無効にしてある場合、GridView は、ポストバックのたびに、基になるデータ ストアに再バインドされます。それにより、直ちに更新されて、これら 2 つの製品が廃止になったことが反映されます (図 17 を参照)。 しかし、GridView でビュー状態を無効にしていない場合は、この変更を加えた後で、手動でデータを GridView に再バインドする必要があります。 これを実現するには、DiscontinueAllProductsForSupplier(supplierID)
メソッドを呼び出した直後に GridView の DataBind()
メソッドを呼び出します。
図 17: [Discontinue All Products] (すべての製品を廃止) ボタンをクリックするとそれに応じてサプライヤーの製品が更新される (クリックするとフルサイズの画像が表示されます)
手順 6: ビジネス ロジック層に製品価格調整用の UpdateProduct オーバーロードを作成する
FormView 内の [Discontinue All Products] (すべての製品を廃止) ボタンと同様に、製品の価格を増減するためのボタンを GridView に追加するには、まず、データ アクセス層 (DAL) とビジネス ロジック層 (BLL) の適切なメソッドを追加する必要があります。 DAL 内に 1 つの製品行を更新するメソッドが既に存在するため、BLL 内の UpdateProduct
メソッドに新しいオーバーロードを作成すると、このような機能を提供できます。
過去の UpdateProduct
のオーバーロードでは、製品フィールドの組み合わせがスカラー入力値として取得され、その後、指定した製品のフィールドのみが更新されました。 このオーバーロードの場合は、この標準と少し異なり、代わりに製品の ProductID
と、UnitPrice
を調整する割合を渡します (調整した新しい UnitPrice
自体を渡すのではない)。 この方法では、現在の製品の UnitPrice
を特定する必要がないため、ASP.NET ページの分離コード クラスで記述する必要があるコードが簡単になります。
このチュートリアルの 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
値が割り当てられているかどうかが確認されます。 そうであれば、価格はそのままになります。 ただし、NULL
UnitPrice
以外の値がある場合、メソッドは指定されたパーセント (unitPriceAdjustmentPercent
) で製品のUnitPrice
を更新します。
手順 7: GridView に増減ボタンを追加する
GridView (および DetailsView) は、どちらもフィールドのコレクションから成ります。 ASP.NET には、BoundField、CheckBoxField、TemplateField に加え、ButtonField が含まれています。これは、その名前が示しているように、各行に Button、LinkButton、または ImageButton がある列としてレンダリングされます。 FormView と同様に、GridView のページング ボタン、編集または削除ボタン、並べ替えボタンなどのボタンをクリックすると、ポストバックが発生し、GridView の RowCommand
イベントが発生します。
ButtonField には、指定された値をそのボタンの CommandName
プロパティにそれぞれ割り当てる CommandName
プロパティがあります。 FormView と同様に、CommandName
値は、RowCommand
イベント ハンドラーで、どのボタンがクリックされたかを判断するために使われます。
2 つの新しい ButtonField を GridView に追加しましょう。一方はボタン テキストが [Price +10%] (価格 +10%) で、もう一方は [Price -10%] (価格 -10%) です。 これらの ButtonField を追加するには、GridView のスマート タグから [列の編集] リンクをクリックし、左上のリストからフィールドの種類として ButtonField を選択し、[追加] ボタンをクリックします。
図 18: GridView に 2 つの ButtonField を追加する
それら 2 つの ButtonField を移動して、最初の 2 つの GridView フィールドとして表示されるようにします。 次に、これら 2 つの ButtonField の Text
プロパティを Price +10% と Price -10% に、CommandName
プロパティをそれぞれ IncreasePrice と DecreasePrice に設定します。 既定では、ButtonField ではボタンの列が LinkButton としてレンダリングされます。 ただし、これは ButtonField の ButtonType
プロパティを使って変更できます。 これら 2 つの ButtonField を通常のプッシュ ボタンとしてレンダリングされるようにしましょう。そのために、ButtonType
プロパティを Button
に設定します。 図 19 で、これらの変更を加えた後の [フィールド] ダイアログ ボックスを示し、その後に、GridView の宣言型マークアップを示します。
図 19: ButtonField の Text
、CommandName
、ButtonType
プロパティを構成する
<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%] (価格 +10%) または [Price -10%] (価格 -10%) ボタンがクリックされて発生した場合は、ボタンがクリックされた行の ProductID
を特定してから、ProductsBLL
クラスの 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
[Price +10%] (価格 +10%) または [Price -10%] (価格 -10%) ボタンがクリックされた行の ProductID
を特定するには、GridView の DataKeys
コレクションを参照する必要があります。 このコレクションでは、GridView の各行の DataKeyNames
プロパティで指定されているフィールドの値が保持されます。 ObjectDataSource が GridView にバインドされたときに Visual Studio によって GridView のDataKeyNames
プロパティが ProductID に設定されているため、DataKeys(rowIndex).Value
では、指定された rowIndex の ProductID
が提供されます。
ButtonField では、e.CommandArgument
パラメーターによって、ボタンがクリックされた行の rowIndex が自動的に渡されます。 したがって、[Price +10%] (価格 +10%) または [Price -10%] (価格 -10%) ボタンがクリックされた行の ProductID
を特定するには、Convert.ToInt32(SuppliersProducts.DataKeys(Convert.ToInt32(e.CommandArgument)).Value)
を使います。
[Discontinue All Products] (すべての製品を廃止) ボタンと同様に、GridView のビュー状態を無効にしてある場合には GridView はポストバックのたびに基になるデータ ストアに再バインドされます。それにより、直ちに更新されて、ボタンのどれかをクリックして発生した価格変更が反映されます。 しかし、GridView でビュー状態を無効にしていない場合は、この変更を加えた後で、手動でデータを GridView に再バインドする必要があります。 これを実現するには、UpdateProduct
メソッドを呼び出した直後に GridView の DataBind()
メソッドを呼び出します。
図 20 に、Grandma Kelly's Homestead から提供されている製品を表示しているときのこのページを示します。 図 21 に、[Grandma's Boysenberry Spread] の [Price +10%] (価格 +10%) ボタンが 2 回クリックされ、[Northwoods Cranberry Sauce] の [Price -10%] (価格 -10%) ボタンが 1 回クリックされた後の結果を示します。
図 20: GridView に [Price +10%] (価格 +10%) および [Price -10%] (価格 -10%) ボタンが含まれている (クリックするとフルサイズの画像が表示されます)
図 21: [Price +10%] (価格 +10%) および [Price -10%] (価格 -10%) ボタンを使って 1 番目と 3 番目の製品の価格が更新された (クリックするとフルサイズの画像が表示されます)
Note
GridView (および DetailsView) では、その TemplateField に Button、LinkButton、または ImageButton を追加することもできます。 BoundField と同様に、これらのボタンをクリックするとポストバックが発生して、GridView の RowCommand
イベントが発生します。 ただし、TemplateField にボタンを追加した場合、そのボタンの CommandArgument
は、ButtonField を使っている場合のように自動的にその行のインデックスに設定されることはありません。 RowCommand
イベント ハンドラー内で、クリックされたボタンの行インデックスを特定する必要がある場合は、次のようなコードを使って、手動で、TemplateField 内の宣言構文でそのボタンの CommandArgument
プロパティを設定する必要があります:
<asp:Button runat="server" ... CommandArgument='<%# CType(Container, GridViewRow).RowIndex %>' />
.
まとめ
GridView、DetailsView、FormView コントロールには、Button、LinkButton、または ImageButton を含めることができます。 このようなボタンをクリックすると、ポストバックが発生し、FormView および DetailsView コントロールでは ItemCommand
イベントが発生し、GridView では RowCommand
イベントが発生します。 これらのデータ Web コントロールには、レコードの削除や編集など、コマンド関連の一般的なアクションを処理する機能が組み込まれています。 しかし、クリックすると応答して独自のカスタム コードが実行されるボタンを使うこともできます。
これを実現するには、ItemCommand
または RowCommand
イベントのイベント ハンドラーを作成する必要があります。 このイベント ハンドラーでは、まず、受け取った CommandName
値を確認し、クリックされたボタンを特定してから、適切なカスタム アクションを実行します。 このチュートリアルでは、指定されたサプライヤーのすべての製品を廃止にするためや、特定の製品の価格を 10% 増減するためにボタンと ButtonField を使う方法について説明しました。
プログラミングに満足!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジに取り組んでいます。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。