連載:Microsoft AJAX Library&JavaScriptプログラミング

第2回 PageRequestManagerクラスでUpdatePanelコントロールを極める!

山田 祥寛(http://www.wings.msn.to/
2007/11/16

■非同期ポストバックの優先順位を制御するには?

 ここでは、ページ内で複数の非同期ポストバックが発生した場合に、その優先順位を制御するための方法を見ていこう。

 本題に入る前に、まずはページ内で複数の異なる非同期ポストバックが発生した場合のデフォルトの挙動を確認しておく。UpdatePanelコントロールを複数配置した、以下のようなページを想定してほしい。


Webフォーム(Priority.aspx)のレイアウト
配置しているコントロールとそのプロパティ設定は以下の表のとおり。

コントロール(ID) プロパティ 設定値
ScriptManager(manager)
UpdatePanel(panel) UpdateMode Conditional
Label(lblAsync) Text △(ブランク)
Button(btnUpdate) Text 更新
UpdatePanel(panel2) UpdateMode Conditional
Label(lblAsync2) Text △(ブランク)
Button(btnUpdate2) Text 更新
各コントロールのプロパティ設定

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
  System.Threading.Thread.Sleep(3000) ' 時間稼ぎのためのダミーコード
  lblAsync.Text = DateTime.Now.ToLongTimeString()
  lblAsync2.Text = DateTime.Now.ToLongTimeString()
End Sub
リスト8 ポストバック時に現在時刻をリフレッシュするためのコード(Priority.aspx)

 UpdatePanelコントロールのUpdateModeプロパティは、UpdatePanel更新のタイミングを決定するものだ。この値がデフォルトの「Always」である場合には、ページ上で発生したすべてのポストバックに対して更新処理を行うが、「Conditional」を指定することで特定の条件下でのみ更新処理を行うことができる。具体的な条件とは、以下のとおりだ。

  • 配下の子コントロールでポストバックが発生した場合(ただし、ChildrenAsTriggersプロパティがTrueであること)
  • Triggersプロパティで登録したコントロールでポストバックが発生した場合
  • UpdatePanelコントロールのUpdateプロパティが明示的に呼び出された場合

 ここでは、それぞれのUpdatePanelコントロール配下に配置されたButtonコントロールによって、対応するUpdatePanelだけを更新したいので、双方のUpdateModeプロパティを「Conditional」に設定しておく。

 まずはこの状態で、Priority.aspxを実行し、2つの[更新]ボタンを続けて(片方の非同期ポストバックが終わる前に)クリックしてみよう。するとどうだろう。後で発生した非同期ポストバックだけが処理され、最初の非同期ポストバックは無視されてしまうはずだ。

2つの[更新]ボタンを続けてクリック



非同期処理が完了


2つの[更新]ボタンを続けてクリック
最初に上の[更新]ボタンを、次に(上のUpdatePanel更新が完了する前に)下の[更新]ボタンをクリックすると……、下のUpdatePanelコントロールだけが更新される。

 このように、UpdatePanelコントロールでは「最後の要求を優先」するわけだ。以下の図2は、複数の非同期ポストバックが並行して発生した場合の、イベントの発生フローである。


図2 複数の非同期ポストバックが並行して発生した場合のイベントの発生フロー

 もっとも、場合によっては既定の「後要求優先」ポリシーではなく、特定のトリガによって発生した非同期ポストバックを優先させたいということがあるだろう。

 そのようなケースでも、PageRequestManagerクラスを利用することで、非同期ポストバックの優先順位を制御することが可能だ。具体的には、以下のようなコードを記述すればよい。

<script type="text/javascript">

function pageLoad() {

  var mng = Sys.WebForms.PageRequestManager.getInstance();

  // 非同期ポストバックの初期化時に呼び出される
  // イベント・ハンドラを定義
  mng.add_initializeRequest(

    // ほかの非同期ポストバックが実行中で、かつ、
    // 現在のイベント発生元要素がbtnUpdate以外である場合、
    // 現在の非同期ポストバックをキャンセル
    function(sender, args) {
      if (mng.get_isInAsyncPostBack() &&
              args.get_postBackElement().id != "btnUpdate") {
        args.set_cancel(true);
      }
    }
  );
}
</script>
リスト9 特定の非同期ポストバックを優先して実行するコード(Priority.aspx)

 このように、initializeRequestイベント・ハンドラの中で、

  • 現在、非同期ポストバックが実行中であるか
  • 現在のイベント発生元が「btnUpdate」でないかどうか

を判定し、これら条件を満たしている場合には新しい非同期ポストバックをキャンセルする。これによって、Buttonコントロール「btnUpdate」で発生した非同期ポストバックが常に優先され、途中でほかの非同期ポストバックが割り込もうとした場合にもこれを事前にキャンセルすることができる。

 実際に、動作を確認してみよう。

2つの[更新]ボタンを続けてクリック



非同期処理が完了


2つの[更新]ボタンを続けてクリック
最初に上の[更新]ボタンを、次に(上のUpdatePanel更新が完了する前に)下の[更新]ボタンをクリックすると……、下の更新は取り消され、上のUpdatePanelコントロールだけが更新される。

 上のUpdatePanelコントロールのみが更新されるのを確認できる。


 INDEX
  Microsoft AJAX Library&JavaScriptプログラミング
  第2回 PageRequestManagerクラスでUpdatePanelコントロールを極める!
    1.UpdatePanelコントロールを拡張するPageRequestManagerクラスの基本
    2.ボタンの2重クリックを防止するには?/実行中の非同期ポストバックをキャンセルするには?
  3.非同期ポストバックの優先順位を制御するには?
    4.非同期ポストバックの完了を通知するには?/非同期ポストバック時に発生した例外を処理するには?
    5.部分更新時にサーバサイドから追加情報を取得するには?
 
インデックス・ページヘ  「Microsoft AJAX Library&JavaScriptプログラミング」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間