#contents

*Microsoft ASP.NET AJAXを使う2 [#x8be42c5]

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

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

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

#code(vbnet){{
<%@ 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>
}}

#code(csharp){{
<%@ 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を更新する [#g8083d8c]

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

#code(vbnet){{
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
}}

#code(csharp){{
protected void Button2_Click(object sender, EventArgs e)
{
    Label1.Text = DateTime.Now.ToString();
    Label2.Text = DateTime.Now.ToString();

    //UpdatePanel1を更新する
    UpdatePanel1.Update();
}
}}

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

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

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

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

[[ドキュメントによると>http://asp.net/ajax/documentation/live/mref/P_System_Web_UI_UpdatePanel_ChildrenAsTriggers.aspx]]ChildrenAsTriggersプロパティを使用するのは、2つ以上のUpdatePanelがあり、あるUpdatePanelから他のUpdatePanelを更新させたいが、自分自身は更新させたくないようなケースであるということです。

**入れ子になったUpdatePanel [#t17e3cec]

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

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

#code(vbnet){{
<%@ 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>
}}

#code(csharp){{
<%@ 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に関連付けられていないコントロールで非同期ポストバックを行う [#d0012396]

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

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

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

#code(vbnet){{
<%@ 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>
}}

#code(csharp){{
<%@ 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>
}}

**コメント [#qc92bfdf]
#comment

//これより下は編集しないでください
#pageinfo([[:Category/.NET]] [[:Category/ASP.NET]],2007-12-21 (金) 03:59:45,DOBON!,2008-02-02 (土) 17:58:01,DOBON!)
[ トップ ]   [ 新規 | 子ページ作成 | 一覧 | 単語検索 | 最終更新 | ヘルプ ]