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

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

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

PageRequestManagerクラスによるサンプル

 以上、PageRequestManagerクラスの基本的な構文を理解したところで、より実用的な局面での使い方を、サンプルを通じて紹介していく。なお、特記しない限り、サンプルは前出のBasic.aspxを基に変更分のコードのみを紹介するものとする。

■ボタンの2重クリックを防止するには?(その1)

 まずは、ボタンの2重クリックを防止する方法からだ。ここでは、ボタンが繰り返しクリックされた場合に、エラー・メッセージを表示するとともに、後続の非同期ポストバックをキャンセルする。

[更新]ボタンを2回クリック



非同期処理が完了


2重クリックが発生した場合にエラー・メッセージを表示
ボタンが繰り返しクリックされた場合に、エラー・メッセージを表示するとともに、後続の非同期ポストバックをキャンセルする。

 具体的なJavaScriptのコードは、以下のとおりだ。

<script type="text/javascript">

function pageLoad() {

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

  // 非同期ポストバックの開始前に呼び出される
  // イベント・ハンドラを定義
  mng.add_initializeRequest(
    function(sender, args) {

      // 現在、実行中の非同期通信が存在するかを判定
      if (mng.get_isInAsyncPostBack()) {

        // 非同期通信中である場合にはエラー・メッセージを表示
        $get('lblStatus').innerHTML = '二重クリックが検出されました。時間をおいてから再度試してください。';

        // 後続の処理をキャンセル
        args.set_cancel(true);
      }
    }
  );

  // 非同期ポストバックの完了後に、メッセージをクリア
  mng.add_endRequest(
    function(sender, args) {
      $get('lblStatus').innerHTML = '';
    }
  );
}
</script>
リスト5 2重クリックが発生した場合に後続の非同期ポストバックをキャンセルするコード(DoubleClick.aspx)

 非同期ポストバックが実行中であるかどうかを判定するのは、isInAsyncPostBackプロパティの役割だ(繰り返しであるが、プロパティにアクセスするにはgetアクセサ・メソッドを介すること。つまりget_isInAsyncPostBackメソッドを呼び出す必要がある)。

 ここでは、isInAsyncPostBackプロパティがtrueである場合に、エラー・メッセージの表示と後続要求のキャンセルを行っている。非同期通信のキャンセルを行うには、イベント・ハンドラの第2引数(Sys.EventArgs派生クラス)を介して、cancelプロパティにtrueを設定するだけだ。これによって、これから発生しようとしている非同期要求をキャンセルすることができる。

[参考]マスタ・ページやユーザー・コントロールに組み込まれた要素を取得するには?

 $get関数で、マスタ・ページやユーザー・コントロールなど名前付きコンテナに含まれる要素にアクセスする場合には、注意が必要だ。というのも、ASP.NETでは要素名の一意性を維持するために、(サーバ側のID値とは別に)動的にクライアントIDを生成している。

 例えば、ContentPlaceHolderコントロール(cph)配下のコンテンツ・ページにLabelコントロール(lblStatus)を配置しているようなケースでは、このLabelコントロールに以下のようなクライアントIDが生成されるはずである。

ctl00_cph_lblStatus

 これによって、個々のコンテンツ・ページやユーザー・コントロールに同一ID値の要素が含まれていたとしても、これをアプリケーションから識別できるというわけだ。

 サーバサイドのコーディングでは、このようなクライアントIDの存在をほとんど意識する必要はないが、クライアントサイドではそうはいかない。クライアントサイドで――例えば、$get関数を利用する場合には――個々の要素を特定するために、クライアントIDで指定する必要があるためだ(これまでは、たまたまサーバIDとクライアントIDが等しいケースを扱っていたので気にする必要がなかったにすぎない)。

$get('ctl00_cph_lblStatus').innerHTML = ……

 ちなみに、クライアントIDは自分自身と親のID値をアンダースコア(_)でつないだものとして生成されるので、上記のようにハード・コーディングすることも可能であるが、保守性という観点からは好ましくない(例えば、親コンテナのID値を変更した場合、クライアントIDにも影響が出てしまう)。

 そこで、クライアントID値を指定する場合には、以下のように埋め込みブロック構文を利用するのがより好ましい。ClientIDプロパティは、対応するコントロールのクライアントIDを取得するためのプロパティである。

$get('<%=lblStatus.ClientID %>').innerHTML = ……

■ボタンの2重クリックを防止するには?(その2)

 前項で紹介した方法を利用することで、2重クリックによる2重送信を強制的にキャンセルすることができる。が、発生してしまった2重クリックを後からキャンセルするくらいならば、そもそもボタンそのものを無効化してしまった方が確実と思われるかもしれない。

 もちろん、PageRequestManagerクラスを使えば、そのような処理を実装することも可能だ。その挙動は冒頭の画面で示したとおりである。

<script type="text/javascript">

function pageLoad() {

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

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

    // イベント発生元の要素を無効化
    function(sender, args) {
      args.get_postBackElement().disabled = true;
    }
  );
}
</script>
リスト6 非同期ポストバック時にトリガとなるボタンを無効化するコード(DoubleClick2.aspx)

 イベント発生元の要素(ボタン)を取得するのは、前述したpostBackElementプロパティの役割だ。ここでは、取得した要素オブジェクトのdisabledプロパティをtrueに設定することで、ボタンを無効化している。

 ちなみに、無効化したボタンはendRequestイベントのタイミングで再び有効化しなければならないのではないかと思われる方もいるかもしれないが、これは不要だ。ボタンはUpdatePanelコントロールの配下に含まれるので、非同期ポストバックの終了時に元の状態に書き換えられるためである。

■実行中の非同期ポストバックをキャンセルするには?

 先ほど(DoubleClick.aspx)の例では、これから発生しようとしている非同期ポストバックをキャンセルする方法について紹介したが、PageRequestManagerクラスを利用することで、現在実行中の非同期ポストバックをキャンセルすることも可能だ。

[更新]ボタンをクリック



[キャンセル]ボタンをクリック


[キャンセル]ボタンをクリックすることで、非同期ポストバックを中断

 まずは、先ほどのBasic.aspxに対して、以下のようにいくつかのサーバ・コントロールを追加する。また、それぞれのコントロールに対して、下の表の要領でプロパティ値を設定しておこう。


Webフォーム(Cancel.aspx)のフォーム・レイアウト
追加するコントロールとそのプロパティ設定は以下の表のとおり。

コントロール(ID) プロパティ 設定値
UpdateProgress(prog)
Label(lblUpdate) BackColor #000040
ForeColor White
Text ...更新中...
Button(btnCancel) Text キャンセル
OnClientClick return false;*
各コントロールのプロパティ設定
* 非同期通信を制御するためのトリガとして、ASP.NETのボタン系コントロール(Button、LinkButton、ImageButton)を利用する場合には、クリックのタイミングでポストバックが発生しないよう、OnClientClickプロパティに「return false;」と指定し、クリック・イベントを明示的にキャンセルしている点に注目してほしい。この指定がない場合には、画面全体がリフレッシュされてしまい、サンプルが意図したように動作しないので注意すること。

 UpdateProgressコントロールについては、別稿「DBプログラミング 7つのヒント− 同時実行制御からASP.NET AJAXまで −」の「Hint 5」でも紹介しているので、併せて参照いただきたい。

 これによって、非同期通信中に「...更新中...」というメッセージと、通信をキャンセルするためのボタンが表示されるようになる。次に、この[キャンセル]ボタンに対して、非同期ポストバックを取り消すための機能を追加してみよう。

<script type="text/javascript">

$addHandler(
  $get('btnCancel'),
  'click',
  function() {
    var mng = Sys.WebForms.PageRequestManager.getInstance();
    mng.abortPostBack();
  }
);
</script>
リスト7 [キャンセル]ボタン・クリック時に、非同期ポストバックをキャンセルするコード(Cancel.aspx)

 $addHandler関数は、MS AJAX Libが提供するショートカット関数の1つで、指定された要素に対してイベント・ハンドラを登録する際に使用するものだ。以下に、$addHandler関数の一般的な構文を示す。

$addHandler(
  イベント・ハンドラを関連付ける要素,
  イベント名,
  イベント・ハンドラ
)
$addHandler関数の一般的な構文

 ここでは、Buttonコントロール「btnUpdate」で発生したclickイベントに対して、指定したイベント・ハンドラを関連付けている。イベント・ハンドラの中で行っていることはごく単純、非同期ポストバックを中止しているだけだ。非同期ポストバックを中止するには、PageRequestManagerクラスのabortPostBackメソッドをコールするだけでよい。

[参考]複数のイベント・ハンドラをまとめて登録するには?

 複数のイベント・ハンドラを登録する場合、(もちろん)$addHandler関数を必要な数だけ呼び出しても構わないが、$addHandlers関数(「s」付き)を利用することで、よりシンプルにコードを記述できる。

 $addHandlers関数の一般的な構文は、以下のとおりだ。

$addHandlers(
  イベント・ハンドラを関連付ける要素,
  {
    イベント名 : イベント・ハンドラ,
    イベント名 : イベント・ハンドラ,
    ……
  }
)
$addHandlers関数の一般的な構文


 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 記事ランキング

本日 月間