ajaxToolkit:PopupControlExtender のポップアップで TextBox を表示して ENTER を押すと困ったかんじ
たとえば、
<asp:Label ID="Label1" /> <ajaxToolkit:PopupControlExtender TargetControlID="Label1" PopupControlID="Panel1" /> <asp:Button /> <asp:Panel ID="Panel1"> <asp:UpdatePanel><ContentTemplate> <asp:TextBox OnChanged="TextBox1_Changed" AutoPostback="True" /> </ContentTemplate></asp:UpdatePanel> </asp:Panel>
こんなかんじだろうか。ここで TextBox1_Changed から PopupControlExtender.Commit() を実施し、ENETR キーを押さないでポップアップを閉じるとうまいこと動くのだが、ENTER キーを押すとブラウザがボタンを押して通常の Postback を発生させる。
そうすると、TextBox1_Changed が UpdatePanel の内部と外部で呼び出され、外部からの通常の Postback で PopupControlExtender.Commit() を実行しようとして失敗する。
対応案としては、
- TextBox1_Changed 内で通常の Postback の場合には何もしないようにする
- ENTER キーで通常の Postback を発生しないようにする
- ENTER キーで UpdatePanel の更新が発生するようにする
あたりなんだが、まず最初の方法は、通常の Postback と UpdatePanel の更新のための Postback の判別方法がわからなかった。*1
Client Callback も Microsoft Ajax も、非同期リクエストをうけると Page のインスタンスを生成し、*2そのインスタンスで通常通りの処理を行うんだが、Client Callback では Page.IsCallback が true になるのに対して、Microsoft Ajax では類似の判断要素を発見することができなかった。Microsoft Ajax の場合は、複数の UpdatePanel を同時に更新するため、データキューが ScriptManager で管理されるので ScriptManager あたりに判別プロパティがありそうなもんなんだが。
次に2番目の方法だが、今回の場合、MSDN の kb にあるような keydown イベントを使用することは出来ない。これは、keydown イベントに何を設定しようが、 PopupControlExtender がそれを上書きしてしまうためで、同様の理由で asp:Panel の DefaultButton プロパティも機能しない。
3番目の方法は、ブラウザが押したがるボタンを UpdatePanel の中に配置したり、既存のボタンを UpdatePanel の中に移動したり、Triggers に登録する。