ASP.NETをやったことがある人は、必ず一度はRadioButtonListかCheckBoxListで困ったことがあるはず。
特に理解できないのが、ラジオボタン/チェックボックス本体に属性がつけられない点だ。
<asp:RadioButtonList ID="rblList" runat="server">
<asp:ListItem Value="A" Text="A" class="hoge" />
<asp:ListItem Value="B" Text="B" />
</asp:RadioButtonList>
こうやって書くと誰もが<input type="radio" value="A" class="class"/>
というような出力を期待するが、そうは問屋が卸さない。レンダリングされた結果は、下記のようになる。
<span id="rblList" >
<span class="hoge">
<input id="rblList_0" type="radio" name="ctl00$rblList" value="A">
<label for="rblList_0">A</label>
</span>
<input id="rblList_1" type="radio" name="ctl00$rblList" value="B">
<label for="rblList_1">B</label>
</span>
まず指定した属性は直接inputにはつかず、外側のspanに付与される。また、IDは改変されnameは推定できない値となり、もうjQueryとかで値を取ろうとすると大変な騒ぎなのであります。
また、inputに属性がつけられないためJavaScriptフレームワークの活用も道が遠のく。
そんな絶望感あふれるこれらのコントロールだが、レンダリング方法をカスタマイズする方法がある。
WebControlAdapter
を継承したクラスを作成し、App_Browsers/setting.browser (ファイル名は何でも可)でそのクラスを特定コントロールのレンダリング時に使用する、としておけばこの問題は回避可能だ。
詳細はこちらご参考。古い記事だがあまり知られていないと思う。
How To: Control Adapters
各Itemの処理時に下記のような感じでやっておけば。。。(※実際は、AddAttributeは固定値ではなくコントロール上の属性を設定)
For i As Integer = 0 To targetControl.Items.Count - 1
writer.WriteFullBeginTag("div")
writer.AddAttribute("class", "hoge")
repeaterInfo.RenderItem(ListItemType.Item, i, New RepeatInfo(), writer)
writer.WriteEndTag("div")
Next
レンダリング結果はこんな感じになるはず。
<div>
<input id="rblList_0" type="radio" name="ctl00$rblList" value="A" class="hoge">
<label for="rblList_0">A</label>
</span>
これでだいぶ使いやすくなります。