プログラミング Tips


ページをリロードせずにサーバーとやり取りする方法

最終更新日 2006 年 3 月 15 日

download1.gifv サンプル コードのダウンロード (aspnettips_ClientCallback.msi, 258 KB)

※このサンプルをお使いいただくためには、Visual Studio 2005 が必要です。

入力欄に値を入力するなど、ユーザーがページ上で操作を行う Web ページで、ポストバックを発生させると、ページは再表示されるため、ユーザーが操作した結果はクリアされます。値を維持したい場合には、ポストバックによる値の維持に対応したサーバー コントロールを使うか、ポストバックで渡ってきた値を使い、ページを再構築する必要があります。しかし、ポストバックやページを再構築する処理によりオーバーヘッドが発生するため、パフォーマンスが低下してしまいます。このような問題を回避する方法として、クライアント・コールバックがあります。クライアント・コールバックを使うことで、ポストバックを行わずにサーバーのコードを実行し、クライアントで結果を受け取ることが可能になります。では、実際にクライアント・コールバックの機能を使ってみましょう。

ポストバックを使ったフォーム

はじめに、サンプルとして、項目を選択するとポストバックするリスト ボックスと、選択された項目の値に対応する画像を表示するイメージ コントロールがあるページを用意します(リスト1、リスト2、および図1)。このページで、リスト ボックスの項目を選択すると、ページ全体が更新されていることが確認できます。
今回は、このページと同じものをクライアント・コールバックを使って作りたいと思います。

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="PostBack.aspx.vb" Inherits="_PostBack" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  >
<head runat="server">
    <title>Sample Page</title>
    <script type="text/javascript">
        function ChangeImage()
        {
            document.MyForm.submit();
        }
    </script>
</head>
<body>
    <form id="MyForm" runat="server">
        <table border="1">
            <tr>
                <td>
                    画像番号
                </td>
                <td>
                    <select size="4" name="ListImage" onchange="ChangeImage();">
                        <option value="1">画像1</option>
                        <option value="2">画像2</option>
                        <option value="3">画像3</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>
                    イメージ
                </td>
                <td>
                    <asp:Image ID="Image1" runat="server" ImageUrl="dummy.gif" />
                </td>
            </tr>
        </table>
  </form>
</body>
</html>

リスト1.PostBack.aspx

Partial Class _PostBack
    Inherits System.Web.UI.Page
    Protected Sub MyForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyForm.Load
        Dim strFile As String = "dummy.gif"
        Select Case Page.Request("ListImage")
            Case 1
                strFile = "円.gif"
            Case 2
                strFile = "三角.gif"
            Case 3
                strFile = "四角.gif"
        End Select
        Image1.ImageUrl = strFile
    End Sub
End Class

リスト2.PostBack.aspx.vb

図

図 1 PostBack.aspx のデザイナ画面

サンプル フォームの準備

まず、リスト1 を参考に、リスト3 とリスト4 にあるページを用意します。

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ClientCallback.aspx.vb" Inherits="_ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  >
<head runat="server">
    <title>Sample Page</title>
</head>
<body>
    <form id="MyForm" runat="server">
        <table border="1">
            <tr>
                <td>
                    画像番号
                </td>
                <td>
                    <select size="4" name="ListImage">
                        <option value="1">画像1</option>
                        <option value="2">画像2</option>
                        <option value="3">画像3</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>
                    イメージ
                </td>
                <td>
                    <asp:Image ID="Image1" runat="server" ImageUrl="dummy.gif" />
                </td>
            </tr>
        </table>
  </form>
</body>
</html>

リスト3.ClientCallback.aspx

Partial Class _ClientCallback
    Inherits System.Web.UI.Page
End Class

リスト4.ClientCallback.aspx.vb

ICallbackEventHandler インターフェイスを宣言する

クライアント・コールバックを使用するには、ICallbackEventHandler インターフェイスを実装する必要があります。リスト5 のようにページのクラス宣言の中で ICallbackEventHandler インターフェイスを宣言してください。

Partial Class _ClientCallback
    Inherits System.Web.UI.Page
    Implements System.Web.UI.ICallbackEventHandler
End Class

リスト5.ClientCallback.aspx.vb

サーバー コールバック メソッドを作成する

RaiseCallbackEvent と GetCallbackResult を実装するメソッドを作成します。 RaiseCallbackEvent メソッドは、クライアントからコールされたときに実行される処理を記述したメソッドになり、GetCallbackResult メソッドは、クライアントからコールされた結果をクライアントにバックするメソッドになります。今回のサンプルでは、1 から 3 の番号を指定してクライアントからコールされるので、RaiseCallbackEvent で、それぞれの番号に対応する画像のパスを設定し、GetCallbackResult で設定したパスを戻します。

Private returnValue As String
    Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
        Dim strFile As String = "dummy.gif"
        Select Case eventArgument
            Case 1
                strFile = "円.gif"
            Case 2
                strFile = "三角.gif"
            Case 3
                strFile = "四角.gif"
        End Select
        returnValue = strFile
    End Sub
    Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
        Return returnValue
    End Function

リスト6.ClientCallback.aspx.vb に追加するコード

クライアント コールバック 関数を作成する

コールバックを送信するクライアント関数はサーバー コードで生成します。まず、GetCallbackEventReference メソッドで、クライアント スクリプトによる関数への参照を取得します。このメソッドのパラメータには、ページへの参照、データを渡す引数の名前、コールバック データを受け取るクライアント スクリプト関数の名前、コールバックの呼出し元を特定するコンテキスト値を指定します。取得したクライアント スクリプトを元に関数を作成したら、RegisterClientScriptBlock メソッドでページに挿入します。
今回のサンプルでは、CallServer がコールバックを呼出すクライアント スクリプトの関数になります。

Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim cbReference As String
        cbReference = Page.ClientScript.GetCallbackEventReference(Me, "arg", "ReceiveServerData", "context")
        Dim callbackScript As String = ""
        callbackScript &= "function CallServer(arg, context) { " & cbReference & "} ;"
        Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallServer", callbackScript, True)
    End Sub

リスト7.ClientCallback.aspx.vb に追加するコード

実際にコールバックを呼出すには、ページにあるリスト ボックスの値を CallServer へ渡してコールバックを呼出す ChangeImage 関数を作成し、onchange イベントで呼出します。また、コールバック値を受け取る ReceiveServerData 関数を作成し、コールバック値を受け取ったらイメージを変更するコードを記述します(リスト8)。

  <script type="text/javascript">
        function ChangeImage()
        {
            var lb = document.MyForm.ListImage;
            var imageNo = lb.options[lb.selectedIndex].value
            CallServer(imageNo, "");
        }
        function ReceiveServerData(rcvValue)
        {
            document.MyForm.Image1.src = rcvValue;
        }
    </script>

リスト8.ClientCallback.aspx に追加するコード

完成した ClientCallback.aspx と ClientCallback.aspx.vb は、リスト9 およびリスト10 になり、実行結果は図2 のようになります。

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="ClientCallback.aspx.vb" Inherits="_ClientCallback" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html  >
<head runat="server">
    <title>Sample Page</title>
    <script type="text/javascript">
        function ChangeImage()
        {
            var lb = document.MyForm.ListImage;
            var imageNo = lb.options[lb.selectedIndex].value
            CallServer(imageNo, "");
        }
        function ReceiveServerData(rcvValue)
        {
            document.MyForm.Image1.src = rcvValue;
        }
    </script>
</head>
<body>
    <form id="MyForm" runat="server">
        <table border="1">
            <tr>
                <td>
                    画像番号
                </td>
                <td>
                    <select size="4" name="ListImage" onchange="ChangeImage();">
                        <option value="1">画像1</option>
                        <option value="2">画像2</option>
                        <option value="3">画像3</option>
                    </select>
                </td>
            </tr>
            <tr>
                <td>
                    イメージ
                </td>
                <td>
                    <asp:Image ID="Image1" runat="server" ImageUrl="dummy.gif" />
                </td>
            </tr>
        </table>
  </form>
</body>
</html>

リスト9.ClientCallback.aspx

Partial Class _ClientCallback
    Inherits System.Web.UI.Page
    Implements System.Web.UI.ICallbackEventHandler
    Private returnValue As String
    Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
        Dim strFile As String = "dummy.gif"
        Select Case eventArgument
            Case 1
                strFile = "円.gif"
            Case 2
                strFile = "三角.gif"
            Case 3
                strFile = "四角.gif"
        End Select
        returnValue = strFile
    End Sub
    Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
        Return returnValue
    End Function
    Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim cbReference As String
        cbReference = Page.ClientScript.GetCallbackEventReference(Me, "arg", "ReceiveServerData", "context")
        Dim callbackScript As String = ""
        callbackScript &= "function CallServer(arg, context) { " & cbReference & "} ;"
        Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "CallServer", callbackScript, True)
    End Sub
End Class

リスト10.ClientCallback.aspx.vb

図

図 2. ClientCallback.aspx の実行結果


Page view tracker