ガジェットきのこ

クラウドファンディングで手に入れたガジェットのレビューやたまに.Netのこと

ガジェットきのこ

クラウドファンディングのガジェットを紹介してるサイトはたくさんあるけどレビューしているサイトはあまりない…
なら手に入れたガジェットだけでもレビューしていこうっていうブログ
たまに.Netのことも書くかもしれません

UpdatePanelを用いたラジオボタンリストの非同期ポストバック

そもそも

UpdatePanelとはASP.NET Web Formsで使えるサーバコントロールです。
通常のポストバックの場合、画面全体が再描画されますが、UpdatePanelを使うとAJAXによってUpdatePanelが含んでいるコントロールのみ再描画してくれます。
今どき、MVCじゃなくてWeb Formsなんて…って感じではありますが(私自身はASP.NET MVC経験はないです…)、オープン系システムではまだまだあるのではないでしょうか。

私がある現象にぶつかって色々ググっていたら、勘違いしたまま諦めてしまったらしい方の記事をいくつか見つけましたが、解決策について載っているサイトは見つけられませんでしたので、メモ書き程度に現象と解決策を書きたいと思います。

諦めてしまったらしい方の中にはラジオボタンリストでは非同期ポストバックができない仕様になっていると言っている方もいましたが、ちゃんとできます。MSDNにも、仕様上できないFileUploadコントロール等とは違って書かれていません。

私がぶつかった現象

それはラジオボタンリスト(RadioButtonList)コントロールのSelectedIndexChangedイベントによる非同期ポストバックが発生しないことでした。

同じUpdatePanelの中に存在するドロップダウンリスト(DropDownList)コントロールでは正しく非同期ポストバックが発生していたのですが、ラジオボタンリストだけ通常のポストバックが発生してしまいました。

以下のようなマークアップ。非同期ポストバックでラベルの文言が変わる的な。

<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
    <ContentTemplate>
        <asp:DropDownList id="DropDownList1" AutoPostBack="True" runat="server">
        <asp:RadioButtonList ID="RadioButtonList1" AutoPostBack="True" runat="server" />
        <asp:Label ID="Label1" runat="server" Text="ラベル" />
    </ContentTemplate>
</asp:UpdatePanel>

ドロップダウンリストもラジオボタンリストも項目はサーバサイドで追加。

原因

原因はマークアップ等ではなく、web.configにあります。

<pages ClientIDMode="Static" />

上記例のマークアップの場合、リストアイテム(ListItem)のIDはRadioButtonList1_1、RadioButtonList1_2といった風に振られていきますが、本来Staticは各開発者が責任を持って全てのIDを振るという思想だからなのか非同期ポストバックが正しく動きません。(UpdatePanelのAJAXから正しく参照できない?)

解決策

<pages ClientIDMode="Predictable" />

私がPredictableを選んだだけなのでAutoIDとかでも大丈夫かもしれません。少なくともPredictableであればラジオボタンリストでも非同期ポストバックが正しく動くことが確認できました。
ちなみにPredictableがデフォルト値なので、なにも設定を変えていなければ最初からきちんと動作していると思います。
検証してませんが恐らくチェックボックスリストとかでも同じ現象が起きそうですね。

HTML出力時のIDの生成方法の話なので、JavaScript等でIDがベタ書きされてなければ開発途中で変えても大丈夫だと思います。

余談

私はASP.NET MVCの経験がないので疑問なのですが、どういった場合にASP.NET MVCが選択されるのでしょうか。MVCモデル使いたいだけならJavaとかを使えば、高いVisual Studioを導入しなくてもいいと思います。
現行システムが.NETのクラサバ等で移行したい時とかなのでしょうか?あとは単にその人のスキル的に?