ラジオ ボタンの GridView 列を追加する (VB)
このチュートリアルでは、GridView コントロールにラジオ ボタンの列を追加して、GridView の 1 つの行を選択する、より直感的な方法をユーザーに提供する方法について説明します。
はじめに
GridView コントロールには、多くの組み込み機能が用意されています。 テキスト、画像、ハイパーリンク、ボタンを表示するためのさまざまなフィールドが含まれています。 さらにカスタマイズするためのテンプレートがサポートされています。 マウスを数回クリックするだけで、ボタンを使用して各行を選択できる GridView を作成したり、編集または削除機能を有効にしたりすることができます。 多数の機能が提供されてはいますが、サポートされていない追加の機能を追加する必要がある場合があります。 このチュートリアルと次の 2 つでは、GridView の機能を強化して追加機能を含める方法について説明します。
このチュートリアルと次のチュートリアルでは、行選択プロセスの強化に重点を置きます。 選択可能なマスター GridView と詳細 DetailView を使用してマスター/詳細を表示するで調べたように、選択ボタンを含む GridView に CommandField を追加できます。 クリックするとポストバックが発生し、Select ボタンがクリックされた行のインデックスに GridView の SelectedIndex
プロパティが更新されます。 選択可能なマスター GridView と詳細 DetailView を使用してマスター/詳細を表示するのチュートリアルでは、この機能を使用して、選択した GridView 行の詳細を表示する方法について説明しました。
[選択] ボタンは多くの状況で機能しますが、他の状況ではうまく機能しない場合があります。 ボタンを使用する代わりに、他の 2 つのユーザー インターフェイス要素が一般的に選択に使用されます。ラジオ ボタンとチェック ボックスです。 選択ボタンではなく、各行にラジオ ボタンまたはチェック ボックスが含まれるように、GridView を拡張できます。 ユーザーが GridView レコードの 1 つしか選択できないシナリオでは、[選択] ボタンよりもラジオ ボタンが優先される場合があります。 ユーザーが Web ベースの電子メール アプリケーションなど、複数のレコードを選択できることが可能であり、ユーザーが複数のメッセージを選択して削除したい場合、チェックボックスで [選択] ボタンまたはラジオ ボタンのユーザー インターフェイスでは使用できない機能が提供されます。
このチュートリアルでは、GridView にラジオ ボタンの列を追加する方法について説明します。 このチュートリアルでは、チェックボックスの使用について説明します。
手順 1: GridView を拡張する Web ページを作成する
GridView を拡張してラジオ ボタンの列を含める前に、まず、このチュートリアルと次の 2 つのために必要な ASP.NET ページを Web サイト プロジェクトに作成してみましょう。 EnhancedGridView
という名前の新しいフォルダーを追加することから始めます。 次に、次の ASP.NET ページをそのフォルダーに追加し、各ページを Site.master
マスター ページに関連付けます。
Default.aspx
RadioButtonField.aspx
CheckBoxField.aspx
InsertThroughFooter.aspx
図 1: SqlDataSource 関連のチュートリアルの ASP.NET ページを追加します
他のフォルダーと同様に、EnhancedGridView
フォルダーの Default.aspx
のセクションにチュートリアルが一覧表示されます。 SectionLevelTutorialListing.ascx
ユーザー コントロールではこの機能が提供されていることを思い出してください。 そのため、ソリューション エクスプローラーからページのデザイン ビューにドラッグして、このユーザー コントロールを Default.aspx
に追加します。
図 2: SectionLevelTutorialListing.ascx
ユーザー コントロールを Default.aspx
に追加する (クリックするとフルサイズの画像が表示されます)
最後に、これら 4 つのページをエントリとして Web.sitemap
ファイルに追加します。 具体的には、SqlDataSource コントロール <siteMapNode>
の使用後に次のマークアップを追加します。
<siteMapNode
title="Enhancing the GridView"
url="~/EnhancedGridView/Default.aspx"
description="Augment the user experience of the GridView control.">
<siteMapNode
url="~/EnhancedGridView/RadioButtonField.aspx"
title="Selection via a Radio Button Column"
description="Explore how to add a column of radio buttons in the GridView." />
<siteMapNode
url="~/EnhancedGridView/CheckBoxField.aspx"
title="Selection via a Checkbox Column"
description="Select multiple records in the GridView by using a column of
checkboxes." />
<siteMapNode
url="~/EnhancedGridView/InsertThroughFooter.aspx"
title="Add New Records through the Footer"
description="Learn how to allow users to add new records through the
GridView's footer." />
</siteMapNode>
Web.sitemap
を更新した後、少し時間を取って、ブラウザーを介してチュートリアル Web サイトを表示します。 左側のメニューに、チュートリアルの編集、挿入、削除の項目が含まれるようになりました。
図 3: サイト マップに GridView の拡張チュートリアルのエントリが含まれるようになりました
手順 2: GridView でサプライヤーを表示する
このチュートリアルでは、米国のサプライヤーを一覧表示する GridView を構築し、各 GridView 行にラジオ ボタンを提供します。 ラジオ ボタンを使用してサプライヤーを選択した後、ユーザーはボタンをクリックしてサプライヤーの製品を表示できます。 このタスクは簡単に聞こえるかもしれませんが、特に難しいいくつかの微妙な点があります。 これらの微妙な点を掘り下げる前に、まずサプライヤーを一覧表示する GridView を取得しましょう。
まず、ツールボックスから GridView をデザイナーにドラッグして、EnhancedGridView
フォルダー内の RadioButtonField.aspx
ページを開きます。 GridView ID
を Suppliers
に設定し、そのスマート タグから新しいデータ ソースを作成することを選択します。 具体的には、SuppliersBLL
オブジェクトからデータをプルする SuppliersDataSource
という名前の ObjectDataSource を作成します。
図 4: SuppliersDataSource
という名前の 新しい ObjectDataSource を作成します (クリックするとフルサイズの画像が表示されます)
図 5: SuppliersBLL
クラスを使用するように ObjectDataSource を構成します (クリックするとフルサイズの画像が表示されます)
米国内のサプライヤーのみを一覧表示するため、[SELECT] タブのドロップダウン リストから GetSuppliersByCountry(country)
メソッドを選択します。
図 6: SuppliersBLL
クラスを使用するように ObjectDataSource を構成します (クリックするとフルサイズの画像が表示されます)
[UPDATE] タブで (なし) オプションを選択し、[次へ] をクリックします。
図 7: SuppliersBLL
クラスを使用するように ObjectDataSource を構成します (クリックするとフルサイズの画像が表示されます)
GetSuppliersByCountry(country)
メソッドはパラメーターを受け取るので、データ ソースのウィザードによって、そのパラメーターのソースの入力を求められます。 ハード コーディングされた値 (この例では USA) を指定するには、[パラメーター ソース] ドロップダウン リストを [なし] に設定したまま、テキスト ボックスに既定値を入力します。 [完了] をクリックして、ウィザードを完了します。
図 8: country
パラメーターの既定値として USA を使用します (クリックしてフルサイズの画像を表示する)
ウィザードが完了すると、GridView には各サプライヤー データ フィールドの BoundField が含まれます。 CompanyName
、City
、Country
BoundFields 以外のすべてを削除し、CompanyName
BoundFields HeaderText
プロパティの名前を Supplier に変更します。 その後、GridView および ObjectDataSource 宣言構文は次のようになります。
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliersByCountry" TypeName="SuppliersBLL">
<SelectParameters>
<asp:Parameter DefaultValue="USA" Name="country" Type="String" />
</SelectParameters>
</asp:ObjectDataSource>
このチュートリアルでは、選択したサプライヤーの製品をサプライヤー リストと同じページまたは別のページで表示できるようにします。 これに対応するには、2 つのボタン Web コントロールをページに追加します。 ListProducts
がクリックされるとポストバックが発生し、選択されたサプライヤーの製品が同じページにリストされますが、SendToProducts
がクリックされると、ユーザーは製品を一覧表示する別のページに移動されるという考えで、これら 2 つのボタンの ID
を SendToProducts
と ListProducts
に設定しました。
図 9 は、ブラウザーで表示したときの Suppliers
GridView と 2 つのボタン Web コントロールを示しています。
図 9: 米国のサプライヤーの名前、市区町村、国の情報が一覧表示されている (クリックしてフルサイズの画像を表示する)
手順 3: ラジオ ボタンの列を追加する
この時点で、Suppliers
GridView には 3 つの BoundFields があり、米国内の各サプライヤーの会社名、市区町村、および国が表示されます。 ただし、まだラジオ ボタンの列がありません。 残念ながら、GridView には組み込みの RadioButtonField は含まれていません。あればグリッドに追加して実行できます。 代わりに、TemplateField を追加し、ラジオ ボタンをレンダリングするように ItemTemplate
を構成し、GridView 行ごとにラジオ ボタンを作成できます。
最初は、TemplateField の ItemTemplate
に RadioButton Web コントロールを追加することで、目的のユーザー インターフェイスを実装できると考えるかもしれません。 これは実際に GridView の各行に 1 つのラジオ ボタンを追加しますが、ラジオ ボタンをグループ化できないため、相互に排他的ではありません。 つまり、エンド ユーザーは GridView から複数のラジオ ボタンを同時に選択できます。
RadioButton Web コントロールの TemplateField を使用しても、必要な機能は提供されませんが、結果として得られるラジオ ボタンがグループ化されていない理由を調べる価値があるため、このアプローチを実装しましょう。 まず、Suppliers GridView に TemplateField を追加し、左端のフィールドに設定します。 次に、GridView のスマート タグから [テンプレートの編集] リンクをクリックし、RadioButton Web コントロールをツールボックスから TemplateField の ItemTemplate
にドラッグします (図 10 を参照)。 RadioButton の ID
プロパティを RowSelector
に、GroupName
プロパティを SuppliersGroup
に設定します。
図 10: RadioButton Web コントロールを ItemTemplate
に追加する (クリックしてフルサイズの画像を表示)
デザイナーを使用してこれらの追加を行った後、GridView のマークアップは次のようになります。
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersDataSource"
EnableViewState="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:RadioButton ID="RowSelector" runat="server"
GroupName="SuppliersGroup" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="CompanyName" HeaderText="Supplier"
SortExpression="CompanyName" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
</Columns>
</asp:GridView>
RadioButton の GroupName
プロパティは、一連のラジオ ボタンをグループ化するために使用されます。 同じ GroupName
値を持つすべての RadioButton コントロールはグループ化されたと見なされます。一度に 1 つのグループから選択できるラジオ ボタンは 1 つだけです。 GroupName
プロパティは、レンダリングされたラジオ ボタンの name
属性の値を指定します。 ブラウザーで、ラジオ ボタンの name
属性が検証され、ラジオ ボタンのグループ化が決定されます。
RadioButton Web コントロールが ItemTemplate
に追加された状態で、ブラウザーからこのページにアクセスし、グリッドの行のラジオ ボタンをクリックします。 ラジオ ボタンがグループ化されていないことに注意してください。図 11 に示すように、すべての行を選択できます。
図 11: GridView のラジオ ボタンがグループ化されていない (クリックしてフルサイズの画像を表示)
ラジオ ボタンがグループ化されない理由は、同じ GroupName
プロパティ設定を持っているにもかかわらず、レンダリングされた name
属性が異なるためです。 これらの違いを確認するには、ブラウザーからビュー/ソースを実行し、ラジオ ボタンのマークアップを調べます。
<input id="ctl00_MainContent_Suppliers_ctl02_RowSelector"
name="ctl00$MainContent$Suppliers$ctl02$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl03_RowSelector"
name="ctl00$MainContent$Suppliers$ctl03$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl04_RowSelector"
name="ctl00$MainContent$Suppliers$ctl04$SuppliersGroup"
type="radio" value="RowSelector" />
<input id="ctl00_MainContent_Suppliers_ctl05_RowSelector"
name="ctl00$MainContent$Suppliers$ctl05$SuppliersGroup"
type="radio" value="RowSelector" />
name
と id
の両方がプロパティ ウィンドウで指定された正確な値ではなく、他の ID
値の数字が先頭に付加されていることに注意してください。 レンダリングされる id
と name
属性の前面に追加される追加の ID
値は、ラジオ ボタン親コントロールの ID
、GridViewRow
の ID
、GridView の ID
、コンテンツ コントロールの ID
、Web フォームの ID
です。 これらの ID
は、GridView のレンダリングされた各 Web コントロールに一意の id
と name
値が含まれるように追加されます。
レンダリングされるコントロールはそれぞれ異なる name
と id
が必要です。なぜなら、ブラウザーがクライアント側の各コントロールを一意に識別する方法と、ポストバックで発生したアクションまたは変更を Web サーバーに確認する方法であるためです。 たとえば、RadioButton のチェック状態が変更されるたびに、サーバー側のコードを実行したいとします。 これを実現するには、RadioButton の AutoPostBack
プロパティを True
に設定し、CheckChanged
イベントのイベント ハンドラーを作成します。 ただし、すべてのラジオ ボタンのレンダリングされた name
と id
値が同じであった場合、ポストバック時に、クリックされた特定の RadioButton を判定できません。
要点は、RadioButton Web コントロールを使用して GridView にラジオ ボタンの列を作成できないということです。 代わりに、適切なマークアップが各 GridView 行に挿入されるように、かなり古い手法を使用する必要があります。
Note
RadioButton Web コントロールと同様に、テンプレートに追加されたラジオ ボタン HTML コントロールには一意の name
属性が含まれるため、グリッド内のラジオ ボタンはグループ化されません。 HTML コントロールに慣れていない場合、特に ASP.NET 2.0 では HTML コントロールはほとんど使用されないため、この注意を無視してください。 詳細については、K. Scott Allen のブログ エントリ「Web コントロールと HTML コントロール 」を参照してください。
リテラル コントロールを使用してラジオ ボタン マークアップを挿入する
GridView 内のすべてのラジオ ボタンを正しくグループ化するには、ラジオ ボタンマークアップを ItemTemplate
に手動で挿入する必要があります。 各ラジオ ボタンには同じ name
属性が必要ですが、一意の id
属性が必要です (クライアント側スクリプトを使用してラジオ ボタンにアクセスする場合)。 ユーザーがラジオ ボタンを選択してページをポストバックすると、ブラウザーは選択したラジオ ボタンの value
属性の値を返します。 そのため、各ラジオ ボタンには一意の value
属性が必要です。 最後に、ポストバック時に、選択されている 1 つのラジオ ボタンに checked
属性を追加する必要があります。そうしないと、ユーザーが選択を行ってポストバックした後、ラジオ ボタンは既定の状態 (すべて未選択) に戻ります。
低レベルのマークアップをテンプレートに挿入するために使用できる方法は 2 つあります。 1 つは、マークアップと、分離コード クラスで定義されている書式設定メソッドの呼び出しを組み合わせて実行することです。 この手法は、最初に GridView コントロールの TemplateFields の使用に関するチュートリアルで説明しました。 この例では、次のようになります。
<input type="radio" id='<%# GetUniqueRadioButtonID(...) %>'
name='SuppliersGroup' value='<%# GetRadioButtonValue(...) %>' ... />
ここで、GetUniqueRadioButton
と GetRadioButtonValue
は、各ラジオ ボタンに対して適切な id
と value
属性値を返した分離コード クラスで定義されたメソッドです。 この方法は、id
と value
属性を割り当てるのに適していますが、データ バインド構文は、データが GridView に最初にバインドされたときにのみ実行されるため、checked
属性値を指定する必要がある場合は不十分です。 そのため、GridView でビュー状態が有効になっている場合、書式設定メソッドは、ページが最初に読み込まれた場合 (または GridView がデータ ソースに明示的にリバインドされた場合) にのみ起動するため、checked
属性を設定する関数はポストバックでは呼び出されません。 これはかなり微妙な問題であり、この記事の範囲を少し超えているので、ここで話を終えます。 しかし、上記のアプローチを使用して、立ち往生するところまで試してみることをお勧めします。 このような演習では、本番のバージョンに近づくことはありませんが、GridView とデータ バインドのライフサイクルをより深く理解するのに役立ちます。
テンプレートにカスタムの低レベルのマークアップを挿入するもう 1 つの方法と、このチュートリアルで使用するアプローチは、テンプレートにLiteral コントロールを追加することです。 次に、GridView の RowCreated
または RowDataBound
イベント ハンドラーで、Literal コントロールにプログラムでアクセスし、その Text
プロパティをマークアップに設定して出力できます。
まず、TemplateField の ItemTemplate
から RadioButton を削除し、Literal コントロールに置き換えます。 Literal コントロールの ID
を RadioButtonMarkup
に設定します。
図 12: リテラル コントロールを ItemTemplate
に追加する (クリックしてフルサイズの画像を表示)
次に、GridView の RowCreated
イベントのイベント ハンドラーを作成します。 RowCreated
イベントは、データが GridView にリバインドされているかどうかに関係なく、追加されたすべての行に対して 1 回発生します。 つまり、ポストバック時にデータがビュー状態から再読み込みされても、RowCreated
イベントは引き続き発生します。これが、RowDataBound
(データがデータ Web コントロールに明示的にバインドされている場合にのみ発生) の代わりにこれを使用する理由です。
このイベント ハンドラーでは、データ行を処理する場合にのみ続行します。 データ行ごとに、プログラムによって RadioButtonMarkup
Literal コントロールを参照し、出力するマークアップにその Text
プロパティを設定します。 次のコードに示すように、出力されるマークアップでは、name
属性が SuppliersGroup
に、id
属性が RowSelectorX
設定に設定されているラジオ ボタンが作成されます。ここで、X は GridView 行のインデックスであり、その value
属性が GridView 行のインデックスに設定されています。
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}" />", e.Row.RowIndex)
End If
End Sub
GridView 行が選択され、ポストバックが発生したとき、選択したサプライヤーの SupplierID
に関心があります。 したがって、各ラジオ ボタンの値は (GridView 行のインデックスではなく) 実際の SupplierID
である必要があると考えるかもしれません。 これは特定の状況で動作する可能性がありますが、SupplierID
を盲目的に受け入れて処理することはセキュリティ上のリスクになります。 たとえば、この GridView では、米国内のサプライヤーのみが一覧表示されます。 しかし、SupplierID
がラジオ ボタンから直接渡された場合、いたずらなユーザーがポストバック時に返される SupplierID
値を操作するのを止めるにはどうしたらいいでしょうか。 行インデックスを value
として使用し、DataKeys
コレクションからポストバック時に SupplierID
を取得することで、ユーザーが GridView 行のいずれかに関連付けられているいずれかの SupplierID
値のみを使用していることを確認できます。
このイベント ハンドラー コードを追加した後、ブラウザーでページをテストするのに 1 分使います。 最初に、グリッド内のラジオ ボタンを一度に 1 つだけ選択できることに注意してください。 ただし、ラジオ ボタンを選択していずれかのボタンをクリックすると、ポストバックが発生し、ラジオ ボタンがすべて初期状態に戻ります (つまり、ポストバックでは、選択したラジオ ボタンが未選択になります)。 これを修正するには、ポストバックから送信された選択されたラジオ ボタン インデックスを検査し、行インデックスの一致する出力マークアップに checked="checked"
属性を追加するように、RowCreated
イベント ハンドラーを拡張する必要があります。
ポストバックが発生すると、ブラウザーから選択したラジオ ボタンの name
と value
が返されます。 この値は Request.Form("name")
を使用してプログラムで取得できます。 Request.Form
プロパティは、フォーム変数を表す NameValueCollection
を提供します。 フォーム変数は、Web ページ内のフォーム フィールドの名前と値であり、ポストバックが発生するたびに Web ブラウザーによって返されます。 GridView のラジオ ボタンのレンダリングされた name
属性は SuppliersGroup
であり、Web ページがポストバックされると、ブラウザーから (他のフォーム フィールドと共に) Web サーバーに SuppliersGroup=valueOfSelectedRadioButton
が送り返されます。 この情報は、Request.Form("SuppliersGroup")
を使用して Request.Form
プロパティからアクセスできます。
RowCreated
イベント ハンドラーだけでなく、Button Web コントロールの Click
イベント ハンドラーで、選択したラジオ ボタンインデックスを決定する必要があるため、ラジオ ボタンが選択されていない場合に -1
を返し、ラジオ ボタンのいずれかが選択されている場合は選択したインデックスを返す SuppliersSelectedIndex
プロパティを分離コード クラスに追加しましょう。
Private ReadOnly Property SuppliersSelectedIndex() As Integer
Get
If String.IsNullOrEmpty(Request.Form("SuppliersGroup")) Then
Return -1
Else
Return Convert.ToInt32(Request.Form("SuppliersGroup"))
End If
End Get
End Property
このプロパティを追加すると、SuppliersSelectedIndex
と e.Row.RowIndex
が等しい場合に RowCreated
イベント ハンドラーに checked="checked"
マークアップを追加することがわかります。 イベント ハンドラーを更新して、次のロジックを含めます。
Protected Sub Suppliers_RowCreated(sender As Object, e As GridViewRowEventArgs) _
Handles Suppliers.RowCreated
If e.Row.RowType = DataControlRowType.DataRow Then
' Grab a reference to the Literal control
Dim output As Literal = _
CType(e.Row.FindControl("RadioButtonMarkup"), Literal)
' Output the markup except for the "checked" attribute
output.Text = String.Format( _
"<input type="radio" name="SuppliersGroup" " & _
"id="RowSelector{0}" value="{0}"", e.Row.RowIndex)
' See if we need to add the "checked" attribute
If SuppliersSelectedIndex = e.Row.RowIndex Then
output.Text &= " checked="checked""
End If
' Add the closing tag
output.Text &= " />"
End If
End Sub
この変更により、選択したラジオ ボタンはポストバック後も選択されたままになります。 選択されているラジオ ボタンを指定する機能が用意できたので、ページが最初にアクセスされたときに、(現在の動作である既定でラジオ ボタンが未選択ではなく) 最初の GridView 行のラジオ ボタンが選択されるように動作を変更できます。 既定で最初のラジオ ボタンを選択するには、If SuppliersSelectedIndex = e.Row.RowIndex Then
ステートメントを If SuppliersSelectedIndex = e.Row.RowIndex OrElse (Not Page.IsPostBack AndAlso e.Row.RowIndex = 0) Then
のように変更します。
この時点で、グループ化されたラジオ ボタンの列を GridView に追加しました。これにより、単一の GridView 行を選択し、ポストバック間で記憶することができます。 次の手順では、選択したサプライヤーから提供される製品を表示します。 手順 4 では、ユーザーを別のページにリダイレクトし、選択した SupplierID
を共に送信する方法について説明します。 手順 5 では、選択したサプライヤーの製品を同じページの GridView に表示する方法について説明します。
Note
TemplateField (この長い手順 3 の焦点) を使用するのではなく、適切なユーザー インターフェイスと機能をレンダリングするカスタム DataControlField
クラスを作成できます。 この DataControlField
クラスは、BoundField、CheckBoxField、TemplateField、およびその他の組み込みの GridView フィールドと DetailsView フィールドの派生元となる基本クラスです。 カスタム DataControlField
クラスを作成すると、宣言構文を使用するだけでラジオ ボタンの列を追加でき、他の Web ページや他の Web アプリケーションでの機能のレプリケートも大幅に容易になります。
ただし、ASP.NET でカスタムのコンパイル済みコントロールを作成したことがある場合は、かなりの量のレッグワークが必要であり、慎重に処理する必要がある多くの機微とエッジ ケースが含まれることがわかります。 そのため、ここではラジオ ボタンの列をカスタム DataControlField
クラスとして実装することを見越し、TemplateField オプションを使用します。 カスタム DataControlField
クラスの作成、使用、デプロイについては、今後のチュートリアルで説明します。
手順 4: 選択したサプライヤーの製品を別のページに表示する
ユーザーが GridView 行を選択したら、選択したサプライヤーの製品を表示する必要があります。 状況によっては、これらの製品を別のページに表示したい場合もあれば、同じページで表示したい場合もあります。 まず、製品を別のページに表示する方法を調べてみましょう。手順 5 では、GridView を RadioButtonField.aspx
に追加して選択したサプライヤーの製品を表示する方法について説明します。
現在、ページ ListProducts
と SendToProducts
には 2 つのボタン Web コントロールがあります。 ボタンが SendToProducts
クリックされたら、ユーザーを ~/Filtering/ProductsForSupplierDetails.aspx
に送る必要があります。 このページは、2 つのページでマスター/詳細をフィルター処理するに関するチュートリアルで作成され、SupplierID
という名前の querystring フィールドを通じて SupplierID
が渡されるサプライヤーの製品を表示します。
この機能を提供するには、SendToProducts
Button の Click
イベントのイベント ハンドラーを作成します。 手順 3 では、オプション ボタンが選択されている行のインデックスを返す SuppliersSelectedIndex
プロパティを追加しました。 対応する SupplierID
は GridView の DataKeys
コレクションから取得でき、その後 Response.Redirect("url")
を使ってユーザーを ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
に送ることができます。
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End Sub
このコードは、GridView からラジオ ボタンの 1 つが選択されている限り、すばらしい動作をします。 最初に GridView にラジオ ボタンが選択されておらず、ユーザーが SendToProducts
ボタンをクリックすると、-1
が SuppliersSelectedIndex
になり、-1
は DataKeys
コレクションのインデックス範囲外であるために例外がスローされます。 ただし、GridView の最初のラジオ ボタンが最初に選択されるように、手順 3 で説明したように RowCreated
イベント ハンドラーを更新することにした場合は、これは問題ではありません。
SuppliersSelectedIndex
の -1
値を格納するには、GridView の上のページにラベル Web コントロールを追加します。 ID
プロパティを ChooseSupplierMsg
に、その CssClass
プロパティを Warning
に、その EnableViewState
と Visible
プロパティを False
に、その Text
プロパティを [グリッドからサプライヤーを選択してください] に設定します。 CSS クラス Warning
は、赤、斜体、太字、大きなフォントでテキストを表示し、で Styles.css
定義されています。 EnableViewState
と Visible
プロパティを False
に設定すると、コントロールの Visible
プロパティがプログラムによって True
に設定されているポストバックのみを除き、ラベルはレンダリングされません。
図 13: GridView の上にラベル Web コントロールを追加する (クリックしてフルサイズの画像を表示)
次に、Click
イベント ハンドラーを拡張して、SuppliersSelectedIndex
が 0 未満の場合に ChooseSupplierMsg
ラベル表示し、それ以外の場合はユーザーを ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID
にリダイレクトするようにします。
Protected Sub SendToProducts_Click(sender As Object, e As EventArgs) _
Handles SendToProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
Else
' Send the user to ~/Filtering/ProductsForSupplierDetails.aspx
Dim supplierID As Integer = _
Convert.ToInt32(Suppliers.DataKeys(SuppliersSelectedIndex).Value)
Response.Redirect( _
"~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=" & _
supplierID)
End If
End Sub
ブラウザーでページにアクセスし、SendToProducts
ボタンをクリックしてから GridView からサプライヤーを選択します。 図 14 に示すように、ChooseSupplierMsg
ラベルが表示されます。 次に、サプライヤーを選択し、SendToProducts
ボタンをクリックします。 これにより、選択したサプライヤーから提供された製品の一覧が表示されるページが表示されます。 図 15 は、Bigfoot Breweries サプライヤーが選択された ProductsForSupplierDetails.aspx
ページを示しています。
図 14: サプライヤーが選択されていない場合、ChooseSupplierMsg
ラベルが表示される (クリックしてフルサイズの画像を表示)
図 15: 選択したサプライヤーの製品が ProductsForSupplierDetails.aspx
に表示される (クリックしてフルサイズの画像を表示)
手順 5: 選択したサプライヤーの製品を同じページに表示する
手順 4 では、ユーザーを別の Web ページに送り、選択したサプライヤーの製品を表示する方法を確認しました。 その他に、選択したサプライヤーの製品を同じページに表示することもできます。 これを説明するために、別の GridView を RadioButtonField.aspx
に追加して選択したサプライヤーの製品を表示します。
この製品の GridView は、サプライヤーが選択された後にのみ表示されるようにするため、Suppliers
GridView の下に Panel Web コントロールを追加し、ID
を ProductsBySupplierPanel
に、その Visible
プロパティを False
に設定します。 パネル内で、選択したサプライヤーのテキスト製品と、その後に ProductsBySupplier
という名前の GridView を追加します。 GridView のスマート タグから、ProductsBySupplierDataSource
という名前の新しい ObjectDataSource にバインドすることを選択します。
図 16: ProductsBySupplier
GridView を新しい ObjectDataSource にバインドする (クリックしてフルサイズの画像を表示)
次に、ProductsBLL
クラスを使用するように ObjectDataSource を構成します。 選択したサプライヤーが提供する製品のみを取得するため、ObjectDataSource が GetProductsBySupplierID(supplierID)
メソッドを呼び出してデータを取得するように指定します。 [UPDATE]、[INSERT]、[DELETE] のタブのドロップダウン リストから (None) に選択します。
図 17: GetProductsBySupplierID(supplierID)
メソッドを使用するように ObjectDataSource を構成する (クリックするとフルサイズの画像が表示されます)
図 18: [UPDATE]、[INSERT]、[DELETE] タブのドロップダウン リストを (None) に設定する (クリックしてフルサイズの画像を表示)
[SELECT]、[UPDATE]、[INSERT]、[DELETE] タブを構成したら、[次へ] をクリックします。 GetProductsBySupplierID(supplierID)
メソッドは入力パラメーターを必要とするため、データ ソースの作成ウィザードでは、パラメーターの値のソースを指定するように求められます。
ここでは、パラメーターの値のソースを指定する方法がいくつかあります。 既定の Parameter オブジェクトを使用し、ObjectDataSource の Selecting
イベント ハンドラーの Parameter の DefaultValue
プロパティに SuppliersSelectedIndex
プロパティの値をプログラムで割り当てることができます。 ObjectDataSource のパラメーターにプログラムで値を割り当てる方法を再確認するには、ObjectDataSource のパラメーター値のプログラムによる設定に関するチュートリアルに戻って参照してください。
または、ControlParameter を使用して Suppliers
GridView の SelectedValue
プロパティを参照することもできます (図 19 を参照)。 GridView の SelectedValue
プロパティは、SelectedIndex
プロパティに対応する DataKey
値を返します。 このオプションを機能させるには、ListProducts
ボタンがクリックされたときに、選択された行に GridView の SelectedIndex
プロパティをプログラムで設定する必要があります。 追加の利点として、SelectedIndex
を設定することで、選択したレコードに DataWebControls
テーマ (黄色の背景) で定義されている SelectedRowStyle
が適用されます。
図 19: ControlParameter を使用して GridView の SelectedValue をパラメーター ソースとして指定する (クリックしてフルサイズの画像を表示)
ウィザードが完了すると、Visual Studio によって製品のデータ フィールドのフィールドが自動的に追加されます。 ProductName
、CategoryName
、UnitPrice
BoundFields 以外のすべてを削除し、HeaderText
プロパティを Product、Category、Price に変更します。 値が通貨として書式設定されるように UnitPrice
BoundField を構成します。 これらの変更を行った後、Panel、GridView、ObjectDataSource の宣言型マークアップは次のようになります。
<asp:Panel runat="server" ID="ProductsBySupplierPanel" Visible="False">
<h3>
Products for the Selected Supplier</h3>
<p>
<asp:GridView ID="ProductsBySupplier" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsBySupplierDataSource" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsBySupplierDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProductsBySupplierID" TypeName="ProductsBLL">
<SelectParameters>
<asp:ControlParameter ControlID="Suppliers" Name="supplierID"
PropertyName="SelectedValue" Type="Int32" />
</SelectParameters>
</asp:ObjectDataSource>
</p>
</asp:Panel>
この演習を完了するには、ListProducts
ボタンがクリックされたときに GridView の SelectedIndex
プロパティを SelectedSuppliersIndex
に、ProductsBySupplierPanel
パネルの Visible
プロパティを True
に設定する必要があります。 これを実現するには、ListProducts
Button Web コントロールの Click
イベントのイベント ハンドラーを作成し、次のコードを追加します。
Protected Sub ListProducts_Click(sender As Object, e As EventArgs) _
Handles ListProducts.Click
' make sure one of the radio buttons has been selected
If SuppliersSelectedIndex < 0 Then
ChooseSupplierMsg.Visible = True
ProductsBySupplierPanel.Visible = False
Else
' Set the GridView's SelectedIndex
Suppliers.SelectedIndex = SuppliersSelectedIndex
' Show the ProductsBySupplierPanel panel
ProductsBySupplierPanel.Visible = True
End If
End Sub
GridView からサプライヤーが選択されていない場合は、ChooseSupplierMsg
ラベルが表示され、ProductsBySupplierPanel
パネルが非表示になります。 それ以外の場合、サプライヤーが選択されている場合、ProductsBySupplierPanel
が表示され、GridView の SelectedIndex
プロパティが更新されます。
図 20 は、Bigfoot Breweries サプライヤーが選択され、[ページに製品を表示] ボタンがクリックされた後の結果を示しています。
図 20: Bigfoot Breweries によって提供される製品が同じページに一覧表示される (クリックしてフルサイズの画像を表示)
まとめ
選択可能なマスター GridView と詳細 DetailView を使用してマスター/詳細を表示するのチュートリアルで説明したように、ShowSelectButton
プロパティが True
に設定されている CommandField を使用して GridView からレコードを選択できます。 ただし、CommandField には、通常のプッシュ ボタン、リンク、またはイメージとしてボタンが表示されます。 別の行選択ユーザー インターフェイスは、各 GridView 行にラジオ ボタンまたはチェック ボックスを提供することです。 このチュートリアルでは、ラジオ ボタンの列を追加する方法について説明しました。
残念ながら、ラジオ ボタンの列の追加は、予想以上に簡単でもシンプルでもありません。 ボタンをクリックして追加できる組み込みの RadioButtonField はなく、TemplateField 内で RadioButton Web コントロールを使用すると、独自の一連の問題が発生します。 最後に、このようなインターフェイスを提供するには、カスタム DataControlField
クラスを作成するか、RowCreated
イベント中に適切な HTML を TemplateField に挿入する必要があります。
ラジオ ボタンの列を追加する方法について説明したので、チェック ボックスの列の追加に注目します。 チェック ボックスの列を使用すると、ユーザーは 1 つ以上の GridView 行を選択し、選択したすべての行に対して何らかの操作を実行できます (Web ベースの電子メール クライアントから一連の電子メールを選択し、選択したすべてのメールを削除することを選択するなど)。 次のチュートリアルでは、このような列を追加する方法について説明します。
プログラミングに満足!
著者について
Scott Mitchell 氏は、ASP/ASP.NET に関する 7 冊の本の著者であり、4GuysFromRolla.com の設立者でもあります。1998 年以降、Microsoft の Web テクノロジを活用した業務を行っています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。
特別な感謝
このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は David Suru でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、 にmitchell@4GuysFromRolla.com行をドロップしてください。