ASP.NET Webフォーム Ajax利用

Ajaxとは?

Asynchronous JavaScript XML
WEBページの一部を変更したい時に、
ページ全体を更新せずに一部分だけを更新する技術
XMLHttpRequest(ブラウザに組み込まれたJavaScript組み込みクラス)クラスにおける非同期通信によってなされる。
非同期通信を行うとFormLoadイベント等は発生するがページ全体の更新は行われないので、ブラウザの「戻る」ボタン等も有効にならない。

Ajax通信時のロード処理

Ajax通信時もPostBackは発生する(=Page_Loadイベントが発生する)。
Page.IsPostBack = True
ただしクライアント側において全画面の再描画は行われない。

通常
Buttonクリック→サーバー処理→全画面再描画
Ajax通信時
Buttonクリック→サーバー処理→指定部分再描画

※~.aspx
<script>
 function myFunc() {
  window.alert("LoadOK");
 }
</script>
<body onload="myFunc();">
 <asp:ScriptManager ID="manager" runat="server"></asp:ScriptManager>
 <asp:UpdatePanel ID="myUpdate" runat="server">
  <ContentTemplate>
   <asp:TextBox ID="myText" runat="server"></asp:TextBox><br />
  </ContentTemplate>   
  <Triggers>
   <asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click" />
  </Triggers>
 </asp:UpdatePanel>
 <asp:Button ID="myButton" runat="server" Text="Button" onclick="myButton_Click" />
</body>

※~.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
 if (!Page.IsPostBack)
 {
  this.myText.Text = "NoPostBack";
 }
 else
 {
  this.myText.Text = "PostBack";
 }
}
protected void myButton_Click(object sender, EventArgs e)
{
 this.myText.Text = "Ajax";
}

【初回ロード時】
サーバー:
Page_Loadイベント

Page.IsPostBack = False なので、this.myText.Text = "NoPostBack";

クライアント:
画面描画

onloadイベント

fncInitSpread()実行

【ボタンクリック時】
サーバー:
Page_Loadイベント

Page.IsPostBack = True なので、this.myText.Text = "PostBack";

クライアント:
UpdatePanel内のみ描画

※onloadイベントは発生しない

AJAX Extensionsコントロール

ASP.NETでは「ASP.NET AJAX Extensionsコントロール」を配置する事でAjaxを利用できる。
ASP.NET AJAX Extensionsコントロールには、
・UpdatePanel
等があり、
UpdatePanel上のデータを非同期でページ全体のポストバックを発生させずに更新できる。
非同期ポストバックと呼ばれる画面一部のポストバックは発生する

ScriptManagerコントロール

UpdatePanel等のAjax Extensionsコントロールを使用する際、
先頭に配置する事で配下のコントロールの非同期通信を可能にする。

UpdatePanelコントロール

※~.aspx
<form id="myForm" runat="server">
 ※スクリプトマネージャー:AJAXを有効にする
 <asp:ScriptManager ID="myScriptManager" runat="server"></asp:ScriptManager>
 
 ※Updateパネル:パネル内のコントロールについて非同期通信を行う
 <asp:UpdatePanel ID="myUpdatePanel" runat="server" >
  <ContentTemplate>
   <asp:Label ID="myLabel" runat="server" Text=""></asp:Label>
  </ContentTemplate>
  
  ※↓のイベントをトリガーとして↑パネル内のみ非同期通信を行う
  <Triggers>
   <asp:AsyncPostBackTrigger ControlID="myButton" EventName="Click" />
  </Triggers>
  
 </asp:UpdatePanel>
 ※↓ボタン押下イベントハンドラをaspx.csファイルに記述
 <asp:Button ID="myButton" runat="server"
   Text="非同期更新" OnClick="myButton_Click" />
</form>

※~.aspx.cs
public partial class MyForm : System.Web.UI.Page
{

 protected void myButton_Click(object sender, EventArgs e)
 {
  // 非同期通信処理
  this.myLabel.Text = this.myTextBox.Text;
  
  ※複数のUpdateパネルを使用している場合に、
  規定のトリガー以外で非同期通信を実行する場合

  hisUpdatePanel.Update();
 }
}

UpdateProgressコントロール

※~.aspx
<form id="myForm" runat="server">
 <asp:ScriptManager ID="myScriptManager" runat="server"></asp:ScriptManager>
 
 <asp:UpdatePanel ID="myUpdatePanel" runat="server">
  <ContentTemplate>
   <asp:Label ID="myLabel" runat="server"
    Text="処理前"></asp:Label><br />
   <asp:Button ID="myButton" runat="server"
    Text="非同期更新" OnClick="myButton_Click" /><br />
  </ContentTemplate>
 </asp:UpdatePanel>
 
 // ↑の非同期処理中のみ表示される
 <asp:UpdateProgress ID="myUpdateProgress" runat="server"
   AssociatedUpdatePanelID="myUpdatePanel">
  <ProgressTemplate>
   <asp:Image ID="myLoading" runat="server"
    // myUpdatePanelが通信中のみ表示される。
    ImageUrl="(gif画像パス)" />
    しばらくお待ちください。
  </ProgressTemplate>
 </asp:UpdateProgress>
</form>

※~.aspx.cs
public partial class MyForm : System.Web.UI.Page
{

 protected void myButton_Click(object sender, EventArgs e)
 {
  // 非同期通信処理
  ~
  this.myLabel.Text = "完了";
 }
}

非同期通信後のスクリプト埋め込み

Updateパネル内の非同期通信処理発生時にサーバーサイドからクライアントサイドへスクリプトを埋め込み/実行させる場合
(非同期通信中は通常のポストバックが発生しない為、Page.~の埋め込みは使用できない)
※UpdatePanel内に配置したコントロール(ボタン等)のイベント内に書く事
ScriptManager.RegisterClientScriptBlock(
 ページ,
 スクリプトを埋め込むコントロールの型,
 キー,
 スクリプト文,
 <script>タグを追加するか否か?);
ScriptManager.RegisterClientScriptBlock(
 this,
 this.GetType(),
 "myKey",
 "fnMyfunc();",
 true);
→<script>fnMyFunc();</script>
ScriptManager.RegisterClientScriptBlock(
 this,
 this.GetType(),
 "myKey",
 "<script>fnMyFunc();</script>",
 false);
→<script>fnMyFunc();</script>

参考:通常ポストバック時のスクリプト埋め込み

画面の表示前にスクリプトを実行する
Page.RegisterClientScriptBlock(型, キー, スクリプト文)
Page.RegisterClientScriptBlock(this.GetType(), "client", "<script> alert('前') <" + "/script>");
画面の表示後にスクリプトを実行する
Page.RegisterStartupScript(型, キー, スクリプト文)
Page.RegisterStartupScript(this.GetType(), "startup", "<script> alert('後') <" + "/script>");

AJAX Control Toolkit

ToolkitScriptManagerコントロール

ScriptManagerコントロールとほぼ同等の機能を持つ
ToolkitScriptManager.CombineScriptsプロパティ=True により、
Ajaxに関わる重複するJavaScriptファイルをダウンロードせずに済ませられる。

UpdatePanelAnimationExtenderコントロール

<ajaxToolkit:UpdatePanelAnimationExtender
 ID="~"
 runat="server"
 
 Ajax通信が実行されるコントロールを指定。
 TargetControlID="~">
 
 対象コントロールの通信終了後に、指定のアニメーションを実行する。
 <Animations>
  更新完了時のアニメーションを定義
  <OnUpdated>
   <Sequence>
    ラベルの背景色を#008800(緑)から#FFFFFF(白)に変更
    <Color AnimationTarget="lblAsync"
     PropertyKey="backgroundColor"
     StartValue="#008800" EndValue="#FFFFFF" />
    
    JavaScript関数を実行
    <ScriptAction Script="myJsFunc();" />
   </Sequence>
  </OnUpdated>
 </Animations>
</ajaxToolkit:UpdatePanelAnimationExtender>

Microsoft AJAX Library

クライアントサイド技術
・Sys.WebForms.PageRequestManagerクラス
UpdatePanelコントロールによって発生した非同期通信(部分更新)を管理
サーバーサイドのUpdatePanelコントロールの機能を拡張する技術
JavaScriptから利用する。
・Sys.Applicationクラス
ページ全体に関わる部分を管理

<script type="text/javascript">
 function pageLoad()
 {
  // PageRequestManagerインスタンスの作成(newではない)
  var mng = Sys.WebForms.PageRequestManager.getInstance();
  
  // 非同期通信の開始と同時に実行される。
  mng.add_initializeRequest(
   function (sender, args) {
    $get('lblStatus').innerHTML =
      args.get_postBackElement().id
        + 'から非同期ポストバックが実行されました。';
   }
  );
  
  // 非同期通信の終了と同時に実行される。
  mng.add_endRequest(
   function (sender, args) {
    $get('lblStatus').innerHTML = '';
   }
  );
 }
</script>