はじめに
GridViewコントロールなどのデータバインドコントロール内では、コントロールのIDなどのプロパティがユニークになるような接頭辞が付加されます。これは、ラジオボタンのグループも対象となってしまうため、複数の要素にまたがってグループ化することができません。
本稿では、コントロールを拡張して複数の要素にまたがるグループ化を行うラジオボタンを作成します。
対象読者
- ASP.NETでのアプリケーションの開発者。
- Web サーバー コントロールの開発経験があるとよい。
必要な環境
Microsoft Visual Studio 2005上で動作確認しています。
現象
冒頭に記した現象を確認するため、下記のページを作成します。
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"> <Columns> <asp:TemplateField> <ItemTemplate> <asp:RadioButton ID="RadioButton1" runat="server" GroupName="Radio" Checked='<%# Eval("IsChecked") %>' /> </ItemTemplate> </asp:TemplateField> <asp:BoundField DataField="Name" /> <asp:BoundField DataField="Value" /> </Columns> </asp:GridView>
このソースでは、テンプレート内のRadioButtonコントロールにGroupName
プロパティを設定して、すべてのItemTemplate内のラジオボタンからどれか1つを選択することを意図しています。
これを実行すると、下記の表示が行われます。
しかし、ラジオボタンを選択すると、複数選択できてしまいます。
原因を確認するために、このページをソース表示して生成されたHTMLを確認します。
<tr> <td> <input id="GridView1_ctl02_RadioButton1" type="radio" name="GridView1$ctl02$Radio" value="RadioButton1" /> </td><td>First</td><td>First Item</td> </tr> <tr> <td> <input id="GridView1_ctl03_RadioButton1" type="radio" name="GridView1$ctl03$Radio" value="RadioButton1" /> </td><td>Second</td><td>Second Item</td> </tr> <tr> <td> <input id="GridView1_ctl04_RadioButton1" type="radio" name="GridView1$ctl04$Radio" value="RadioButton1" checked="checked" /> </td><td>Third</td><td>Selected Item</td> </tr> <tr> <td> <input id="GridView1_ctl05_RadioButton1" type="radio" name="GridView1$ctl05$Radio" value="RadioButton1" /> </td><td>Fourth</td><td>Fourth Item</td> </tr> <tr> <td> <input id="GridView1_ctl06_RadioButton1" type="radio" name="GridView1$ctl06$Radio" value="RadioButton1" /> </td><td>Fifth</td><td>Fifth Item</td> </tr>
name
属性に行ごとの接頭辞がついてしまうため、同一のグループとはみなされないのが原因のようです。
アンケートページのように、行ごとに1項目を選択する場合にはこの挙動が必要になりますが、今回のように「縦方向」の対象から選択する場合には通常のRadioButtonコントロールではうまくいきません。
前述の出力されたHTMLを見ると、変更したい部分は2点あります。
name
属性から行ごとの接頭辞を外す。これは、グループ化するために必要となります。value
属性に行ごとの接頭辞をつける。これは、どのボタンが押されたかを判別するために必要となります。
ASP.NETにおけるコントロールの描画はRender
メソッドで行われます。RadioButtonコントロールの場合、ここから呼ばれる仮想メソッドは特になさそうなので、このメソッドをオーバーライドすれば希望通りの描画が実現できます。しかし、この方法では描画のすべてを自前で行わなければならないので、別の方法を考えます。
メカニズム
ASP.NETにおけるコントロールの描画は、下図の流れで行われます。
コントロールのRender
メソッドで、HtmlTextWriter
に対してエレメントや属性を登録してから描画すると、HtmlTextWriter
はその内容をHTMLに直して、保持しているTextWriter
に出力します。その結果、TextWriter
がHTMLを出力します。
このHtmlTextWriter
とTextWriter
との関係は、Decoratorパターンとなっています。
Decoratorパターンは、もともとの処理とDecoratorが同じインターフェイスを実装し、Decoratorがそのインターフェイスを呼び出すことによって、複数のDecoratorを付加することができるようになるパターンです。
すなわち、今回のコントロールの描画においても、もともとのHtmlTextWriter
にさらにHtmlTextWriter
を付加することができます。ここで、属性値を変更して出力することになります。