非同期ポストバックのキャンセル
更新 : 2007 年 11 月
.NET UpdatePanel Web サーバー コントロールをページで使用すると、ASP.NET の非同期ポストパックが実装されます。UpdatePanel コントロールを使用すると、ポストバックのたびにページ全体を更新する必要がなくなり、ユーザー エクスペリエンスが改善されます。ブラウザでは、Microsoft AJAX Library の Sys.WebForms.PageRequestManager クラスが、非同期ポストバックのクライアント ページ ライフ サイクルにおけるイベントを管理します。PageRequestManager クラスが公開しているイベントを処理することで、非同期ポストバックの発生方法をカスタマイズできます。
このチュートリアルでは、PageRequestManager クラスの initializeRequest イベントを使用して、現在実行されている非同期ポストバックをキャンセルします。
PageRequestManager クラスで発生するイベントの順序については、「PageRequestManager のイベントの処理」を参照してください。
前提条件
この手順を各自の開発環境で実行するには、以下が必要です。
Microsoft Visual Studio 2005 または Microsoft Visual Web Developer Express Edition。
AJAX 対応の ASP.NET Web サイト。
ポストバックをキャンセルするスクリプトの作成
最初にブラウザでの非同期ポストバックを管理する ECMAScript (JavaScript) コードを作成します。
ポストバックをキャンセルする JavaScript コードを作成するには
ASP.NET Web サイトに新しい JScript ファイルを追加し、CancelPostback.js という名前を付けます。
次のスクリプトをファイルに追加します。
var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; Sys.Application.add_load(ApplicationLoadHandler) function ApplicationLoadHandler(sender, args) { Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckStatus); } function CheckStatus(sender, args) { var prm = Sys.WebForms.PageRequestManager.getInstance(); if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'CancelRefresh') { prm.abortPostBack(); } else if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') { args.set_cancel(true); ActivateAlertDiv('visible', 'Still working on previous request.'); } else if (!prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') { ActivateAlertDiv('visible', 'Retrieving headlines.'); } } function ActivateAlertDiv(visString, msg) { var adiv = $get(divElem); var aspan = $get(messageElem); adiv.style.visibility = visString; aspan.innerHTML = msg; } if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
var divElem = 'AlertDiv'; var messageElem = 'AlertMessage'; Sys.Application.add_load(ApplicationLoadHandler) function ApplicationLoadHandler(sender, args) { Sys.WebForms.PageRequestManager.getInstance().add_initializeRequest(CheckStatus); } function CheckStatus(sender, args) { var prm = Sys.WebForms.PageRequestManager.getInstance(); if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'CancelRefresh') { prm.abortPostBack(); } else if (prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') { args.set_cancel(true); ActivateAlertDiv('visible', 'Still working on previous request.'); } else if (!prm.get_isInAsyncPostBack() & args.get_postBackElement().id == 'RefreshButton') { ActivateAlertDiv('visible', 'Retrieving headlines.'); } } function ActivateAlertDiv(visString, msg) { var adiv = $get(divElem); var aspan = $get(messageElem); adiv.style.visibility = visString; aspan.innerHTML = msg; } if(typeof(Sys) !== "undefined") Sys.Application.notifyScriptLoaded();
このスクリプトは、次のタスクを実行します。
Sys.Application クラスの load イベントのイベント ハンドラを定義します。このハンドラは、PageRequestManager クラスの initializeRequest イベントを処理する CheckStatus という名前のハンドラを登録します。
CheckStatus ハンドラを定義します。このハンドラは、非同期ポストバックが現在実行されているかどうか確認し、ポストバックの発生元である要素の名前を特定します。
ActivateAlertDiv 関数を定義します。この関数は、メッセージの表示に使用される <div> 要素の表示と非表示を切り替えます。
UpdatePanel コントロールに対するスクリプトの使用
この手順では、UpdatePanel コントロールを含むページで、作成したスクリプトを使用します。非同期ポストバックの進行中にユーザーがリンクをクリックすると、このスクリプトによりポストバックがキャンセルされます。
ユーザーがポストバックをキャンセルできるページを作成するには
Default.aspx という名前の 1 つのファイルで構成される新しい ASP.NET Web ページを作成し、デザイン ビューに切り替えます。
ツールボックスの [AJAX Extensions] タブで、ScriptManager コントロールをダブルクリックしてページに追加します。
ツールボックスで、UpdatePanel コントロールをダブルクリックしてページに追加します。
ソース ビューに切り替えて、ページの <head> 要素の <style> ブロックに、次のスタイル ルールを追加します。
<style type="text/css"> body { font-family: Tahoma; } #UpdatePanel1{ width: 400px; height: 200px; border: solid 1px gray; } div.AlertStyle { font-size: smaller; background-color: #FFC080; width: 400px; height: 20px; visibility: hidden; } </style>
<style type="text/css"> body { font-family: Tahoma; } #UpdatePanel1{ width: 400px; height: 200px; border: solid 1px gray; } div.AlertStyle { font-size: smaller; background-color: #FFC080; width: 400px; height: 20px; visibility: hidden; } </style>
このスタイル ルールでは、UpdatePanel コントロールによってレンダリングされる <div> 要素の高さと幅が定義されます。またこのルールでは、進行状況メッセージを表示する、入れ子になった <div> 要素の外観も定義されます。
<asp:UpdatePanel> 要素の <ContentTemplate> 要素内に次のマークアップを追加します。
<asp:DataList ID="HeadlineList" runat="server"> <HeaderTemplate> <strong>Headlines</strong> </HeaderTemplate> <ItemTemplate> <%# Eval("Value") %> </ItemTemplate> <FooterTemplate> </FooterTemplate> <FooterStyle HorizontalAlign="right" /> </asp:DataList> <p style="text-align:right"> <asp:Button ID="RefreshButton" Text="Refresh" runat="server" OnClick="NewsClick_Handler" /> </p> <div id="AlertDiv" class="AlertStyle"> <span id="AlertMessage"></span> <asp:LinkButton ID="CancelRefresh" runat="server"> Cancel</asp:LinkButton>
<asp:DataList ID="HeadlineList" runat="server"> <HeaderTemplate> <strong>Headlines</strong> </HeaderTemplate> <ItemTemplate> <%# Eval("Value") %> </ItemTemplate> <FooterTemplate> </FooterTemplate> <FooterStyle HorizontalAlign="right" /> </asp:DataList> <p style="text-align:right"> <asp:Button ID="RefreshButton" Text="Refresh" runat="server" OnClick="NewsClick_Handler" /> </p> <div id="AlertDiv" class="AlertStyle"> <span id="AlertMessage"></span> <asp:LinkButton ID="CancelRefresh" runat="server"> Cancel</asp:LinkButton>
このマークアップは、次のタスクを実行します。
DataList コントロールを定義します。このコントロールのアイテムは、この手順で後ほど SortedList オブジェクトとして定義される Value フィールドにバインドされます。
Button コントロールを定義します。このコントロールは、非同期ポストバックを発生させます。
<div> 要素を定義します。この要素は、非同期ポストバック中にメッセージを表示するために使用されます。また、<div> 要素には、ポストバックをキャンセルできるようにする LinkButton コントロールが含まれます。
<script runat="server"> 要素に、Click イベント ハンドラとして次のサーバー コードを追加します。これは、UpdatePanel コントロールの [Refresh] ボタンのイベント ハンドラです。
Protected Sub NewsClick_Handler(ByVal sender As Object, ByVal e As EventArgs) System.Threading.Thread.Sleep(2000) HeadlineList.DataSource = GetHeadlines() HeadlineList.DataBind() End Sub
protected void NewsClick_Handler(object sender, EventArgs e) { System.Threading.Thread.Sleep(2000); HeadlineList.DataSource = GetHeadlines(); HeadlineList.DataBind(); }
このコードは、データ バインディングを使用して見出しの一覧を読み込み、DataList コントロールに表示します。
メモ : このチュートリアルでは、Click イベントのハンドラにより意図的に遅延を発生させています。実際には、ユーザーが遅延を発生させることはありません。実際の環境では、サーバー トラフィックや、処理に時間がかかるサーバー コード (長時間実行するデータベース クエリなど) によって遅延が発生します。
<script> 要素内に、ページの Load イベントに関する次のコードを追加します。
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) If Not (IsPostBack) Then HeadlineList.DataSource = GetHeadlines() HeadlineList.DataBind() End If End Sub
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { HeadlineList.DataSource = GetHeadlines(); HeadlineList.DataBind(); } }
このコードは、現在の要求がポストバックかどうかチェックします。要求がポストバックでない場合、DataList コントロールは見出しの一覧にバインドされます (非同期ポストバック中、前の手順で作成した NewClick_Handler メソッドでデータ バインディングが発生します)。
<script> 要素内に、見出しを生成する次のコードを追加します。
' Helper method to simulate news headline fetch. Private Function GetHeadlines() As SortedList Dim headlines As New SortedList() headlines.Add(1, "This is headline 1.") headlines.Add(2, "This is headline 2.") headlines.Add(3, "This is headline 3.") headlines.Add(4, "This is headline 4.") headlines.Add(5, "This is headline 5.") headlines.Add(6, "(Last updated on " & DateTime.Now.ToString() & ")") Return headlines End Function
// Helper method to simulate news headline fetch. private SortedList GetHeadlines() { SortedList headlines = new SortedList(); headlines.Add(1, "This is headline 1."); headlines.Add(2, "This is headline 2."); headlines.Add(3, "This is headline 3."); headlines.Add(4, "This is headline 4."); headlines.Add(5, "This is headline 5."); headlines.Add(6, "(Last updated on " + DateTime.Now.ToString() + ")"); return headlines; }
このチュートリアルでは、見出しは静的な一覧として作成されます。実際のアプリケーションでは、見出しは動的に生成されます。
デザイン ビューに切り替えて、ページが次の図のようになっているか確認します。
ScriptManager コントロールを選択します。
[プロパティ] ウィンドウで、Scripts プロパティをクリックします。次に、省略記号 ([…]) ボタンをクリックして、[ScriptReference コレクション エディタ] ダイアログ ボックスを表示します。
[追加] をクリックしてスクリプト参照を追加します。
スクリプト参照の Path プロパティを CancelPostback.js (前の手順で作成した JavaScript ファイル) に設定します。
ScriptManager の Scripts コレクションを使用してスクリプト参照を追加すると、Microsoft AJAX Library の読み込み後にスクリプトが確実に読み込まれます。
[OK] をクリックして [ScriptReference コレクション エディタ] ダイアログ ボックスを閉じます。
変更内容を保存し、Ctrl キーを押しながら F5 キーを押して、ブラウザでページを表示します。
[Refresh] ボタンをクリックし、パネルが最新の情報に更新されるまで待ちます。
ポストバックをキャンセルするオプションを備えたメッセージが表示されます。
[Refresh] ボタンをもう一度クリックします。メッセージが表示された後、[Refresh] ボタンをもう一度クリックし、パネルが最新の情報に更新されるまで待ちます。
メッセージのテキストが変更され、前の更新がまだ進行中であることが通知されます。2 番目の更新は無視されます。
[Refresh] ボタンをもう一度クリックし、メッセージが表示されたら、[Cancel] リンクをクリックしてポストバックをキャンセルします。
この場合は、非同期ポストバックがキャンセルされたので、UpdatePanel コントロールに表示される時刻は変更されません。
<%@ Page Language="VB" %> <%@ Import Namespace="System.Collections.Generic" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> Protected Sub NewsClick_Handler(ByVal sender As Object, ByVal e As EventArgs) System.Threading.Thread.Sleep(2000) HeadlineList.DataSource = GetHeadlines() HeadlineList.DataBind() End Sub Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) If Not (IsPostBack) Then HeadlineList.DataSource = GetHeadlines() HeadlineList.DataBind() End If End Sub ' Helper method to simulate news headline fetch. Private Function GetHeadlines() As SortedList Dim headlines As New SortedList() headlines.Add(1, "This is headline 1.") headlines.Add(2, "This is headline 2.") headlines.Add(3, "This is headline 3.") headlines.Add(4, "This is headline 4.") headlines.Add(5, "This is headline 5.") headlines.Add(6, "(Last updated on " & DateTime.Now.ToString() & ")") Return headlines End Function </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title>Canceling Postback Example</title> <style type="text/css"> body { font-family: Tahoma; } #UpdatePanel1{ width: 400px; height: 200px; border: solid 1px gray; } div.AlertStyle { font-size: smaller; background-color: #FFC080; width: 400px; height: 20px; visibility: hidden; } </style> </head> <body> <form id="form1" runat="server"> <div > <asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Path="CancelPostback.js" /> </Scripts> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="Server" > <ContentTemplate> <asp:DataList ID="HeadlineList" runat="server"> <HeaderTemplate> <strong>Headlines</strong> </HeaderTemplate> <ItemTemplate> <%# Eval("Value") %> </ItemTemplate> <FooterTemplate> </FooterTemplate> <FooterStyle HorizontalAlign="right" /> </asp:DataList> <p style="text-align:right"> <asp:Button ID="RefreshButton" Text="Refresh" runat="server" OnClick="NewsClick_Handler" /> </p> <div id="AlertDiv" class="AlertStyle"> <span id="AlertMessage"></span> <asp:LinkButton ID="CancelRefresh" runat="server"> Cancel</asp:LinkButton> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
<%@ Page Language="C#" %> <%@ Import Namespace="System.Collections.Generic" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <script runat="server"> protected void NewsClick_Handler(object sender, EventArgs e) { System.Threading.Thread.Sleep(2000); HeadlineList.DataSource = GetHeadlines(); HeadlineList.DataBind(); } protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { HeadlineList.DataSource = GetHeadlines(); HeadlineList.DataBind(); } } // Helper method to simulate news headline fetch. private SortedList GetHeadlines() { SortedList headlines = new SortedList(); headlines.Add(1, "This is headline 1."); headlines.Add(2, "This is headline 2."); headlines.Add(3, "This is headline 3."); headlines.Add(4, "This is headline 4."); headlines.Add(5, "This is headline 5."); headlines.Add(6, "(Last updated on " + DateTime.Now.ToString() + ")"); return headlines; } </script> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title>Canceling Postback Example</title> <style type="text/css"> body { font-family: Tahoma; } #UpdatePanel1{ width: 400px; height: 200px; border: solid 1px gray; } div.AlertStyle { font-size: smaller; background-color: #FFC080; width: 400px; height: 20px; visibility: hidden; } </style> </head> <body> <form id="form1" runat="server"> <div > <asp:ScriptManager ID="ScriptManager1" runat="server"> <Scripts> <asp:ScriptReference Path="CancelPostback.js" /> </Scripts> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="Server" > <ContentTemplate> <asp:DataList ID="HeadlineList" runat="server"> <HeaderTemplate> <strong>Headlines</strong> </HeaderTemplate> <ItemTemplate> <%# Eval("Value") %> </ItemTemplate> <FooterTemplate> </FooterTemplate> <FooterStyle HorizontalAlign="right" /> </asp:DataList> <p style="text-align:right"> <asp:Button ID="RefreshButton" Text="Refresh" runat="server" OnClick="NewsClick_Handler" /> </p> <div id="AlertDiv" class="AlertStyle"> <span id="AlertMessage"></span> <asp:LinkButton ID="CancelRefresh" runat="server"> Cancel</asp:LinkButton> </ContentTemplate> </asp:UpdatePanel> </div> </form> </body> </html>
レビュー
このチュートリアルでは、非同期ポストバックをキャンセルする JavaScript コードを記述する方法を説明しました。スクリプトでは、PageRequestManager クラスの initializeRequest イベントのハンドラを用意しました。initializeRequest イベントでは、どの要素がポストバックを発生させたか、およびポストバックが現在進行中かどうか判断できます。これにより、適切なアクションを実行できます。このチュートリアルでは、<div> 要素を表示するコードにキャンセル ボタンを含めました。
UpdatePanel コントロールのステータスを自動的に表示するには、UpdateProgress コントロールを使用します。詳細については、「UpdateProgress コントロールの概要」を参照してください。
参照
処理手順
クライアント スクリプト内の UpdateProgress コントロールのプログラミング