次の方法で共有


ラジオ ボタンの GridView 列を追加する (VB)

スコット・ミッチェル著

PDF をダウンロードする

このチュートリアルでは、GridView コントロールにラジオ ボタンの列を追加して、GridView の 1 行を選択するより直感的な方法をユーザーに提供する方法について説明します。

イントロダクション

GridView コントロールには、多くの組み込み機能が用意されています。 テキスト、画像、ハイパーリンク、ボタンを表示するためのさまざまなフィールドが含まれています。 さらにカスタマイズするためのテンプレートがサポートされています。 マウスを数回クリックするだけで、ボタンを使用して各行を選択できる GridView を作成したり、編集または削除機能を有効にしたりすることができます。 多数の機能が提供されているにもかかわらず、多くの場合、サポートされていない追加の機能を追加する必要があります。 このチュートリアルと次の 2 つでは、GridView の機能を強化して追加機能を含める方法について説明します。

このチュートリアルと次のチュートリアルでは、行選択プロセスの強化に重点を置きます。 詳細詳細ビューで 選択可能なマスター グリッド ビューを使用してマスター/詳細で調べたように、選択ボタンを含む GridView に CommandField を追加できます。 クリックするとポストバックが発生し、GridView の SelectedIndex プロパティが、Select ボタンがクリックされた行のインデックスに更新されます。 「マスター/詳細選択可能なマスター 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

SqlDataSource-Related チュートリアルの ASP.NET ページを追加する

図 1: SqlDataSource-Related チュートリアルの ASP.NET ページを追加する

他のフォルダーと同様に、Default.aspx フォルダーにEnhancedGridViewすると、そのセクションにチュートリアルが一覧表示されます。 SectionLevelTutorialListing.ascx ユーザー コントロールがこの機能を提供していることを思い出してください。 そのため、ソリューション エクスプローラーからページのデザイン ビューにドラッグして、このユーザー コントロールを Default.aspx に追加します。

SectionLevelTutorialListing.ascx ユーザー コントロールをDefault.aspxに追加する

図 2: SectionLevelTutorialListing.ascxDefault.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 サイトを表示します。 左側のメニューに、チュートリアルの編集、挿入、削除の項目が含まれるようになりました。

サイト マップに、GridView の拡張チュートリアルのエントリが含まれるようになりました

図 3: サイト マップに GridView の拡張チュートリアルのエントリが含まれるようになりました

手順 2: GridView で仕入先を表示する

このチュートリアルでは、米国のサプライヤーを一覧表示する GridView を構築し、各 GridView 行にラジオ ボタンを提供します。 ラジオ ボタンを使用して仕入先を選択した後、ユーザーはボタンをクリックして仕入先の製品を表示できます。 このタスクは簡単に聞こえるかもしれませんが、特に難しいいくつかの微妙な点があります。 これらの機微を掘り下げる前に、まずサプライヤーを一覧表示する GridView を取得しましょう。

まず、ツールボックスからデザイナーに GridView をドラッグして、RadioButtonField.aspx フォルダー内のEnhancedGridView ページを開きます。 GridView の IDSuppliers に設定し、スマート タグから新しいデータ ソースを作成することを選択します。 具体的には、SuppliersDataSource オブジェクトからデータをプルするSuppliersBLLという名前の ObjectDataSource を作成します。

SuppliersDataSource という名前の新しい ObjectDataSource を作成する

図 4: SuppliersDataSource という名前の新しい ObjectDataSource を作成する (フルサイズの画像を表示する をクリックします)

ビジネス オブジェクトのドロップダウン メニューが開いている [データ ソースの構成 - SuppliersDataSource] ウィンドウのスクリーンショット。SuppliersBLL が選択され、[次へ] ボタンが強調表示されます。

図 5: SuppliersBLL クラスを使用するように ObjectDataSource を構成する (フルサイズの画像を表示する場合はこちらをクリック)

米国内のこれらのサプライヤーのみを一覧表示するため、[選択] タブのドロップダウン リストから GetSuppliersByCountry(country) 方法を選択します。

[SELECT] タブの [データ ソースの構成 - SuppliersDataSource] ウィンドウのスクリーンショット。メソッドのドロップダウン メニューが開いています。メソッド オプション GetSupplierByCountry が選択され、[次へ] ボタンが強調表示されています。

図 6: SuppliersBLL クラスを使用するように ObjectDataSource を構成する (フルサイズの画像を表示する をクリックします)。

[更新] タブで 、(なし) オプションを選択し、[次へ] をクリックします。

[更新] タブの [データ ソースの構成 - SuppliersDataSource] ウィンドウのスクリーンショット。メソッドのドロップダウン メニューが開いています。メソッド オプション (なし) が選択され、[次へ] ボタンが強調表示されています。

図 7: SuppliersBLL クラスを使用するように ObjectDataSource を構成する (フルサイズの画像を表示する をクリックします)。

GetSuppliersByCountry(country) メソッドはパラメーターを受け取るので、データ ソースの構成ウィザードによって、そのパラメーターのソースの入力を求められます。 ハード コーディングされた値 (この例では USA) を指定するには、[パラメーター ソース] ドロップダウン リストを [なし] に設定したまま、テキスト ボックスに既定値を入力します。 [完了] をクリックして、ウィザードを完了します。

country パラメーターの既定値として USA を使用する

図 8: country パラメーターの既定値として USA を使用する (フルサイズの画像を表示する をクリックします)

ウィザードが完了すると、GridView には各仕入先データ フィールドの BoundField が含まれます。 BoundFields を除くすべてのCompanyNameCity、およびCountryを削除し、BoundFields CompanyNameプロパティ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 つの Button Web コントロールをページに追加します。 私は、この2つのボタンの IDListProductsSendToProductsに設定しました。 ListProducts をクリックするとポストバックが発生し、選択したサプライヤーの製品が同じページに表示されますが、 SendToProducts がクリックされると、ユーザーは製品を一覧表示する別のページにウィスキーされます。

図 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 に設定します。

ItemTemplate に RadioButton Web コントロールを追加する

図 10: ItemTemplate に RadioButton Web コントロールを追加します (フルサイズの画像を表示する をクリックします)。

デザイナーを使用してこれらの追加を行った後、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 に示すように、すべての行を選択できます。

GridView のラジオ ボタンがグループ化されていない

図 11: GridView のラジオ ボタンがグループ化されていません (フルサイズの画像を表示する をクリックします)。

ラジオ ボタンがグループ化されない理由は、同じnameプロパティ設定を持っているにもかかわらず、レンダリングされたGroupName属性が異なるためです。 これらの違いを確認するには、ブラウザーからビュー/ソースを実行し、ラジオ ボタンのマークアップを調べます。

<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およびid属性の前に追加された追加のname値は、ラジオボタンのIDの親コントロールのGridViewRow、GridView のID、コンテンツコントロールのID、WebフォームのIDです。 これらの ID は、GridView でレンダリングされた各 Web コントロールに一意の idname の値が含まれるように追加されます。

レンダリングされる各コントロールには、異なる nameid が必要です。これは、ブラウザーがクライアント側の各コントロールを一意に識別する方法と、ポストバック時に発生したアクションまたは変更を Web サーバーに識別する方法であるためです。 たとえば、RadioButton のチェック状態が変更されるたびに、サーバー側のコードを実行したいとします。 これを実現するには、RadioButton の AutoPostBack プロパティを True に設定し、 CheckChanged イベントのイベント ハンドラーを作成します。 ただし、すべてのラジオ ボタンのレンダリングされた nameid の値が同じであった場合、ポストバック時にクリックされた特定の RadioButton を特定できませんでした。

その要点は、RadioButton Web コントロールを使用して GridView にラジオ ボタンの列を作成できないことです。 代わりに、適切なマークアップが各 GridView 行に挿入されるように、かなり古い手法を使用する必要があります。

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(...) %>' ... />

ここでは、 GetUniqueRadioButtonGetRadioButtonValue は、各ラジオ ボタンの適切な idvalue 属性値を返す分離コード クラスで定義されたメソッドです。 この方法は、 id 属性と value 属性を割り当てる場合に適していますが、データ バインド構文が実行されるのは、データが GridView に最初にバインドされたときにのみ実行されるため、 checked 属性値を指定する必要がある場合には適していません。 そのため、GridView でビューステートが有効になっている場合、書式設定メソッドは、ページが最初に読み込まれた場合 (または GridView がデータ ソースに明示的にリバインドされている場合) にのみ発生するため、 checked 属性を設定する関数はポストバックでは呼び出されません。 それはかなり微妙な問題であり、この記事の範囲を少し超えているので、私はこれを残します。 あなたが行き詰まるところまで、上記のアプローチを試してみることをお勧めします。 このような演習では、作業バージョンに近づくことはありませんが、GridView とデータ バインドのライフサイクルをより深く理解するのに役立ちます。

テンプレートにカスタムの低レベルのマークアップを挿入するもう 1 つの方法と、このチュートリアルで使用するアプローチは、 テンプレートに Literal コントロール を追加することです。 次に、GridView の RowCreated または RowDataBound イベント ハンドラーで、Literal コントロールにプログラムでアクセスし、その Text プロパティをマークアップに設定して出力できます。

まず、TemplateField の ItemTemplateから RadioButton を削除し、リテラル コントロールに置き換えます。 Literal コントロールの IDRadioButtonMarkupに設定します。

ItemTemplate にリテラル コントロールを追加する

図 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として使用し、SupplierID コレクションからポストバック時にDataKeysを取得することで、ユーザーが GridView 行のいずれかに関連付けられているいずれかのSupplierID値のみを使用していることを確認できます。

このイベント ハンドラー コードを追加した後、ブラウザーでページをテストするのに 1 分かかります。 最初に、グリッド内のラジオ ボタンを一度に 1 つだけ選択できることに注意してください。 ただし、ラジオ ボタンを選択していずれかのボタンをクリックすると、ポストバックが発生し、ラジオ ボタンがすべて初期状態に戻ります (つまり、ポストバックの場合、選択したラジオ ボタンは選択されなくなりました)。 これを修正するには、ポストバックから送信された選択したラジオ ボタン インデックスを検査し、行インデックスの一致する出力マークアップにRowCreated属性を追加するように、checked="checked" イベント ハンドラーを拡張する必要があります。

ポストバックが発生すると、ブラウザーは選択したラジオ ボタンの namevalue を返します。 Request.Form("name")を使用してプログラムで値を取得できます。 Request.Form プロパティは、フォーム変数を表すNameValueCollectionを提供します。 フォーム変数は、Web ページ内のフォーム フィールドの名前と値であり、ポストバックが発生するたびに Web ブラウザーによって返されます。 GridView のラジオ ボタンのレンダリングされた name 属性は SuppliersGroupされているため、Web ページがポストバックされると、ブラウザーは SuppliersGroup=valueOfSelectedRadioButton を (他のフォーム フィールドと共に) Web サーバーに送り返します。 この情報には、Request.Formを使用して、Request.Form("SuppliersGroup") プロパティからアクセスできます。

RowCreated イベント ハンドラーだけでなく、Button Web コントロールのClick イベント ハンドラーでも、選択したラジオ ボタンインデックスを決定する必要があるため、オプション ボタンが選択されていない場合はSuppliersSelectedIndexを返し、いずれかのラジオ ボタンが選択されている場合は選択したインデックスを返す-1プロパティを分離コード クラスに追加します。

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

このプロパティを追加することで、checked="checked"RowCreated と等しい時に、SuppliersSelectedIndex イベントハンドラーで e.Row.RowIndex マークアップを追加する必要があることが分かります。 イベント ハンドラーを更新して、次のロジックを含めます。

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 に表示する方法について説明します。

TemplateField (この長い手順 3 の焦点) を使用するのではなく、適切なユーザー インターフェイスと機能をレンダリングするカスタム DataControlField クラスを作成できます。 DataControlField クラスは、BoundField、CheckBoxField、TemplateField、およびその他の組み込みの GridView フィールドと DetailsView フィールドの派生元となる基本クラスです。 カスタム DataControlField クラスを作成すると、宣言構文を使用するだけでラジオ ボタンの列を追加でき、他の Web ページやその他の Web アプリケーションでの機能のレプリケートも大幅に容易になります。

ただし、ASP.NET でカスタムのコンパイル済みコントロールを作成したことがある場合は、かなりの量のレッグワークが必要であり、慎重に処理する必要がある多くの機微とエッジ ケースが含まれることがわかります。 そのため、現時点ではカスタムDataControlField クラスとしてラジオボタンの列を実装することは見送り、TemplateFieldオプションに固執します。 カスタム DataControlField クラスの作成、使用、デプロイについては、今後のチュートリアルで説明します。

手順 4: 選択した仕入先の製品を別のページに表示する

ユーザーが GridView 行を選択したら、選択した仕入先の製品を表示する必要があります。 状況によっては、これらの製品を別のページに表示したい場合もあれば、同じページで表示したい場合もあります。 まず、製品を別のページに表示する方法を調べてみましょう。手順 5 では、選択した仕入先の製品を表示する RadioButtonField.aspx に GridView を追加する方法について説明します。

現在、ページ ListProductsSendToProductsに 2 つの Button Web コントロールがあります。 SendToProducts ボタンをクリックすると、ユーザーを~/Filtering/ProductsForSupplierDetails.aspxに送信します。 このページは、 マスターページと詳細フィルターのチュートリアル で作成され、 SupplierIDSupplierIDという名前のクエリ文字列フィールドを通じて渡されるサプライヤーの製品を表示します。

この機能を提供するには、 SendToProducts Button の Click イベントのイベント ハンドラーを作成します。 手順 3 では、オプション ボタンが選択されている行のインデックスを返す SuppliersSelectedIndex プロパティを追加しました。 対応するSupplierIDは GridView のDataKeys コレクションから取得でき、ユーザーは ~/Filtering/ProductsForSupplierDetails.aspx?SupplierID=SupplierID を使用してResponse.Redirect("url")に送信できます。

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 ] ボタンをクリックすると、 SuppliersSelectedIndex-1され、 -1DataKeys コレクションのインデックス範囲から外れているため、例外がスローされます。 ただし、手順 3 で説明したように、GridView の最初のラジオ ボタンが最初に選択されるように、 RowCreated イベント ハンドラーを更新することにした場合は、これは問題ではありません。

SuppliersSelectedIndex-1値に対応するには、GridView の上のページに Label Web コントロールを追加します。 IDプロパティをChooseSupplierMsgに設定し、そのCssClassプロパティをWarningに設定し、そのEnableViewStateプロパティとVisibleプロパティをFalseに設定し、そのTextプロパティをグリッドから仕入先を選択してください。 CSS クラス Warning は、赤、斜体、太字、大きなフォントでテキストを表示し、 Styles.cssで定義されています。 EnableViewStateプロパティとVisibleプロパティを False に設定すると、コントロールの Visible プロパティがプログラムによってTrueに設定されているポストバックのみを除き、ラベルはレンダリングされません。

GridView の上にラベル Web コントロールを追加する

図 13: GridView の上にラベル Web コントロールを追加する (フルサイズの画像を表示する をクリックします)

次に、Clickイベント ハンドラーを拡張して、ChooseSupplierMsgが 0 未満の場合は SuppliersSelectedIndex Label を表示し、それ以外の場合はユーザーを ~/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 の醸造所のサプライヤーが選択されたときの ProductsForSupplierDetails.aspx ページを示しています。

仕入先が選択されていない場合は、ChooseSupplierMsg ラベルが表示されます

図 14: 仕入先が選択されていない場合、 ChooseSupplierMsg ラベルが表示されます (フルサイズの画像を表示する をクリックします)。

選択した仕入先の製品がProductsForSupplierDetails.aspxに表示されます

図 15: 選択した仕入先の製品が ProductsForSupplierDetails.aspx に表示されます (フルサイズの画像を表示する をクリックします)。

手順 5: 選択した仕入先の製品を同じページに表示する

手順 4 では、ユーザーを別の Web ページに送信して、選択したサプライヤーの製品を表示する方法を確認しました。 または、選択した仕入先の製品を同じページに表示することもできます。 これを説明するために、選択したサプライヤーの製品を表示する RadioButtonField.aspx に別の GridView を追加します。

この製品の GridView は、サプライヤーが選択された後にのみ表示されるようにするため、 Suppliers GridView の下に Panel Web コントロールを追加し、その IDProductsBySupplierPanel に設定し、 Visible プロパティを False に設定します。 パネル内で、選択したサプライヤーのテキスト製品を追加し、その後に ProductsBySupplierという名前の GridView を追加します。 GridView のスマート タグから、 ProductsBySupplierDataSourceという名前の新しい ObjectDataSource にバインドすることを選択します。

ProductsBySupplier GridView を新しい ObjectDataSource にバインドする

図 16: ProductsBySupplier GridView を新しい ObjectDataSource にバインドします (フルサイズの画像を表示する をクリックします)。

次に、 ProductsBLL クラスを使用するように ObjectDataSource を構成します。 選択したサプライヤーが提供する製品のみを取得するため、ObjectDataSource が GetProductsBySupplierID(supplierID) メソッドを呼び出してデータを取得するように指定します。 [UPDATE]、[INSERT]、[DELETE] タブのドロップダウン リストから [(なし)] を選択します。

GetProductsBySupplierID(supplierID) メソッドを使用するように ObjectDataSource を構成する

図 17: GetProductsBySupplierID(supplierID) メソッドを使用するように ObjectDataSource を構成する (フルサイズの画像を表示する をクリックします)。

UPDATE、INSERT、DELETE タブで Drop-Down リストを (なし) に設定する

図 18: UPDATE、INSERT、および DELETE タブの Drop-Down リストを (なし) に設定します (フルサイズの画像を表示する をクリックします)。

SELECT タブ、UPDATE タブ、INSERT タブ、DELETE タブを構成したら、[次へ] をクリックします。 GetProductsBySupplierID(supplierID) メソッドは入力パラメーターを必要とするため、データ ソースの作成ウィザードでは、パラメーターの値のソースを指定するように求められます。

ここでは、パラメーターの値のソースを指定する方法がいくつかあります。 既定の Parameter オブジェクトを使用し、SuppliersSelectedIndex プロパティの値を ObjectDataSource の DefaultValue イベント ハンドラーの Parameter s Selecting プロパティにプログラムで割り当てることができます。 ObjectDataSource のパラメーターにプログラムで値を割り当てる方法については、ObjectDataSource のパラメーター値のプログラムによる設定に関するチュートリアルを参照してください。

または、ControlParameter を使用して、 Suppliers GridView の SelectedValue プロパティ を参照することもできます (図 19 を参照)。 GridView の SelectedValue プロパティは、DataKey プロパティに対応するSelectedIndex値を返します。 このオプションを機能させるには、SelectedIndex ボタンがクリックされたときに、GridView の ListProducts プロパティを選択した行にプログラムで設定する必要があります。 追加の利点として、SelectedIndexを設定することで、選択したレコードは、SelectedRowStyleテーマ (黄色の背景) で定義されたDataWebControlsに適用されます。

ControlParameter を使用して GridView の SelectedValue をパラメーター ソースとして指定する

図 19: ControlParameter を使用してパラメーター ソースとして GridView s SelectedValue を指定する (フルサイズの画像を表示する をクリックします)

ウィザードが完了すると、Visual Studio によって製品のデータ フィールドのフィールドが自動的に追加されます。 BoundFields を除くすべての ProductNameCategoryNameUnitPrice を削除し、 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>

この演習を完了するには、SelectedIndex ボタンがクリックされたとき、GridView の SelectedSuppliersIndex プロパティを ProductsBySupplierPanel に設定し、Visible パネルの True プロパティを ListProducts に設定する必要があります。 これを実現するには、 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 の醸造所のサプライヤーが選択され、[ページに製品を表示] ボタンがクリックされた後の結果を示しています。

ビッグフットビールが提供する製品は、同じページに掲載されています

図 20: Bigfoot の醸造所によって提供される製品が同じページに一覧表示されます (フルサイズの画像を表示する をクリックします)。

概要

このチュートリアル「選択可能なマスター グリッドビューとディテール ビューの使用」で説明されているように、ShowSelectButton プロパティが True に設定された CommandField を使用して、GridView からレコードを選択できます。 ただし、CommandField には、通常のプッシュ ボタン、リンク、またはイメージとしてボタンが表示されます。 別の行選択ユーザー インターフェイスは、各 GridView 行にラジオ ボタンまたはチェック ボックスを提供することです。 このチュートリアルでは、ラジオ ボタンの列を追加する方法について説明しました。

残念ながら、ラジオ ボタンの列の追加は、予想以上に簡単でも簡単でもないです。 ボタンをクリックしたときに追加できる組み込みの RadioButtonField はなく、TemplateField 内で RadioButton Web コントロールを使用すると、独自の問題のセットが発生します。 最後に、このようなインターフェイスを提供するには、カスタム DataControlField クラスを作成するか、 RowCreated イベント中に適切な HTML を TemplateField に挿入する必要があります。

ラジオ ボタンの列を追加する方法について説明しました。チェック ボックスの列を追加することに注意してください。 チェック ボックスの列を使用すると、ユーザーは 1 つ以上の GridView 行を選択し、選択したすべての行に対して何らかの操作を実行できます (Web ベースの電子メール クライアントから一連の電子メールを選択し、選択したすべてのメールを削除することを選択するなど)。 次のチュートリアルでは、このような列を追加する方法について説明します。

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジを使用しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・セルフ ASP.NET 24時間で2.0です。 彼には mitchell@4GuysFromRolla.comで連絡できます。

特別な感謝

このチュートリアル シリーズは、多くの役に立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は David Suru でした。 今後の MSDN の記事を確認することに関心がありますか? その場合は、mitchell@4GuysFromRolla.comにメッセージを送ってください。