Microsoft ASP.NET AJAXを使う2

前回はUpdatePanelコントロールの基本的な使い方について説明しましたが、今回は一つのページにUpdatePanelを複数配置するケースに絞ってより詳しく説明します。

複数のUpdatePanelがある時に特定のUpdatePanelだけが更新されるようにする

まずは、一つのページにUpdatePanelを複数配置した時にどのようになるか確認してみましょう。そのために、UpdatePanelを2つ配置し、それぞれのUpdatePanelの中にButtonとLabelコントロールを配置したページを作成します。具体的なコードは、以下のようにします。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
<%@ Page Language="VB" %>
 
<!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 Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = DateTime.Now.ToString()
        Label2.Text = DateTime.Now.ToString()
    End Sub
 
 
    Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = DateTime.Now.ToString()
        Label2.Text = DateTime.Now.ToString()
    End Sub
    
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>UpdatePanelテスト</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server" Text="更新1"
                    OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
        <asp:UpdatePanel ID="UpdatePanel2" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button2" runat="server" Text="更新2"
                    OnClick="Button2_Click" />
                <asp:Label ID="Label2" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
<%@ Page Language="C#" %>
 
<!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 Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString();
        Label2.Text = DateTime.Now.ToString();
    }
 
    protected void Button2_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString();
        Label2.Text = DateTime.Now.ToString();
    }
 
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>UpdatePanelテスト</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server" Text="更新1"
                    OnClick="Button1_Click" />
                <asp:Label ID="Label1" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
        <asp:UpdatePanel ID="UpdatePanel2" runat="server">
            <ContentTemplate>
                <asp:Button ID="Button2" runat="server" Text="更新2"
                    OnClick="Button2_Click" />
                <asp:Label ID="Label2" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

このサンプルでは、Button1をクリックしても、Button2をクリックしても、UpdatePanel1とUpdatePanel2の両方が更新されます。このように一つのページに複数のUpdatePanelと複数のトリガーを配置した時、デフォルトでは、どのトリガーを使っても全てのUpdatePanelが更新されます。これは、デフォルトではUpdatePanelのUpdateModeプロパティがAlwaysだからです。

しかし、あるトリガーでは、あるUpdatePanelしか更新しない(例えば上記の例では、Button1をクリックした時はUpdatePanel2は更新せずに、UpdatePanel1しか更新しないなど)というのが決まっているのであれば、上記の例のようにすべてのUpdatePanelが更新されてしまうというのは、無駄が多すぎます。更新しないUpdatePanelの情報(HTML)もサーバーが送信しているのです。

関連付けられたトリガーだけがそのUpdatePanelを更新できるようにするには、UpdateModeプロパティをConditionalにします。例えば、上記のサンプルでButton1をクリックした時だけUpdatePanel1が更新されるようにするには、UpdatePanel1のUpdateModeプロパティをConditionalに変更します。

実際に上記のサンプルのUpdatePanel1のUpdateModeプロパティをConditionalに変更してみてください。このようにすると、Button1をクリックした時はUpdatePanel1とUpdatePanel2の両方が更新されますが、Button2をクリックした時はUpdatePanel1だけが更新されます。つまり、UpdatePanel1はUpdateModeプロパティをConditionalにしたため、Button2ボタンでは更新されず、Button1ボタンでのみ更新できます。UpdatePanel2はUpdateModeプロパティがAlwaysのため、Button1ボタンとButton2ボタンのどちらでも更新されてしまいます。

複数のUpdatePanelをページに配置した時は、UpdatePanelのUpdateModeプロパティをConditionalにするというのが基本となるでしょう。

プログラムでUpdatePanelを更新する

プログラムでUpdatePanelを更新するには、UpdatePanelのUpdateメソッドを呼び出します。例えば、先ほどの最後の例のようにUpdatePanel1のUpdateModeプロパティをConditionalにしたときに、Button2をクリックしてUpdatePanel2も更新されるようにするには、Button2のClickイベントハンドラでUpdatePanel1のUpdateメソッドを呼び出します。

  1
  2
  3
  4
  5
  6
  7
Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
    Label1.Text = DateTime.Now.ToString()
    Label2.Text = DateTime.Now.ToString()
    
    'UpdatePanel1を更新する
    UpdatePanel1.Update()
End Sub
  1
  2
  3
  4
  5
  6
  7
  8
protected void Button2_Click(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToString();
    Label2.Text = DateTime.Now.ToString();
 
    //UpdatePanel1を更新する
    UpdatePanel1.Update();
}

UpdatePanel内のコントローラによってそのUpdatePanelが更新されるのを防ぐ

今で紹介してきた例では、UpdatePanel内にあるコントロールによって、自分自身のUpdatePanelは否応なしに更新されていました。しかし、UpdatePanelのChildrenAsTriggersプロパティをFalseにすることにより、そのUpdatePanelの中にあるコントロールによってそのUpdatePanelが更新されなくなります。

ChildrenAsTriggersプロパティをFalseにするならば、UpdateModeプロパティは必ずConditionalにしなければなりません。UpdateModeプロパティがAlwaysの時にChildrenAsTriggersプロパティをFalseにすると例外がスローされます。

ChildrenAsTriggersプロパティの動作について、具体例を見てみましょう。前の前の例で、UpdatePanel1のUpdateModeプロパティをConditionalに、ChildrenAsTriggersプロパティをFalseにしてみてください。すると、Button1をクリックしてもUpdatePanel1は更新されなくなり、UpdatePanel2だけが更新されるようになります。

ドキュメントによるとChildrenAsTriggersプロパティを使用するのは、2つ以上のUpdatePanelがあり、あるUpdatePanelから他のUpdatePanelを更新させたいが、自分自身は更新させたくないようなケースであるということです。

入れ子になったUpdatePanel

ChildrenAsTriggersプロパティがTrueならば、そのUpdatePanelの中にあるコントロールによってUpdatePanelが更新されると説明しましたが、入れ子のUpdatePanelの場合はちょっと違います。入れ子の親のUpdatePanelのUpdateModeプロパティがConditionalならば、子のUpdatePanel内にあるコントロールによって親のUpdatePanelは更新されません。

例えば以下のような例では、子のUpdatePanel2内にあるButton2をクリックしても、親のUpdatePanel1は更新されません。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
<%@ Page Language="VB" %>
 
<!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 Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = DateTime.Now.ToString()
        Label2.Text = DateTime.Now.ToString()
    End Sub
 
 
    Protected Sub Button2_Click(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = DateTime.Now.ToString()
        Label2.Text = DateTime.Now.ToString()
    End Sub
    
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <!-- 親UpdatePanel -->
        <asp:UpdatePanel ID="UpdatePanel1" runat="server"
            UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server"
                    OnClick="Button1_Click" Text="親更新" />
                <asp:Label ID="Label1" runat="server"></asp:Label>
                <br />
                <!-- 子UpdatePanel -->
                <asp:UpdatePanel ID="UpdatePanel2" runat="server"
                    UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Button2" runat="server"
                            Text="子更新" OnClick="Button2_Click" />
                        <asp:Label ID="Label2" runat="server"></asp:Label>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
<%@ Page Language="C#" %>
 
<!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 Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString();
        Label2.Text = DateTime.Now.ToString();
    }
 
    protected void Button2_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString();
        Label2.Text = DateTime.Now.ToString();
    }
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <!-- 親UpdatePanel -->
        <asp:UpdatePanel ID="UpdatePanel1" runat="server"
            UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Button ID="Button1" runat="server"
                    OnClick="Button1_Click" Text="親更新" />
                <asp:Label ID="Label1" runat="server"></asp:Label>
                <br />
                <!-- 子UpdatePanel -->
                <asp:UpdatePanel ID="UpdatePanel2" runat="server"
                    UpdateMode="Conditional">
                    <ContentTemplate>
                        <asp:Button ID="Button2" runat="server"
                            Text="子更新" OnClick="Button2_Click" />
                        <asp:Label ID="Label2" runat="server"></asp:Label>
                    </ContentTemplate>
                </asp:UpdatePanel>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

親のUpdatePanelが更新されれば、子のUpdatePanelも更新されます。上記の例では、UpdatePanel1にあるButton1をクリックすれば、UpdatePanel2も更新されます。

UpdatePanelに関連付けられていないコントロールで非同期ポストバックを行う

UpdatePanelの中にあるコントロールやUpdatePanelのTriggersプロパティに追加されているコントロールは、通常のコントロールとは異なり、非同期ポストバックのトリガーとなり、Ajax機能を実現させています。このようなコントロールはScriptManagerによって非同期ポストバックコントロールとして登録されます。

これらの方法以外でScriptManagerに非同期ポストバックコントロールを登録するには、ScriptManagerのRegisterAsyncPostBackControlメソッドを使います。通常RegisterAsyncPostBackControlメソッドはページのLoadイベントハンドラで呼び出します。

以下の例では、UpdatePanelの外にあるButton1を非同期ポストバックコントロールとして登録しています。この例では、Button1をクリックすることにより、UpdateModeがAlwaysのUpdatePanel1だけでなく、UpdateModeがConditionalのUpdatePanel2もUpdateメソッドを呼び出して更新しています。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
<%@ Page Language="VB" %>
 
<!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 Page_Load(ByVal sender As Object, ByVal e As EventArgs)
        'Button1を非同期ポストバックコントロールとして登録する
        ScriptManager1.RegisterAsyncPostBackControl(Button1)
    End Sub
 
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs)
        Label1.Text = DateTime.Now.ToString()
   
        Label2.Text = DateTime.Now.ToString()
        'UpdatePanel2を更新する
        UpdatePanel2.Update()
    End Sub
    
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:Button ID="Button1" runat="server" Text="更新"
            OnClick="Button1_Click" />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Label ID="Label1" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
        <asp:UpdatePanel ID="UpdatePanel2" runat="server"
            UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Label ID="Label2" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
<%@ Page Language="C#" %>
 
<!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 Page_Load(object sender, EventArgs e)
    {
        //Button1を非同期ポストバックコントロールとして登録する
        ScriptManager1.RegisterAsyncPostBackControl(Button1);
    }
    
    protected void Button1_Click(object sender, EventArgs e)
    {
        Label1.Text = DateTime.Now.ToString();
 
        Label2.Text = DateTime.Now.ToString();
        //UpdatePanel2を更新する
        UpdatePanel2.Update();
    }
 
</script>
 
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>
        <asp:Button ID="Button1" runat="server" Text="更新"
            OnClick="Button1_Click" />
        <asp:UpdatePanel ID="UpdatePanel1" runat="server">
            <ContentTemplate>
                <asp:Label ID="Label1" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
        <asp:UpdatePanel ID="UpdatePanel2" runat="server"
            UpdateMode="Conditional">
            <ContentTemplate>
                <asp:Label ID="Label2" runat="server"></asp:Label>
            </ContentTemplate>
        </asp:UpdatePanel>
    </div>
    </form>
</body>
</html>

コメント



ページ情報
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]