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.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.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)
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.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)
{
ScriptManager1.RegisterAsyncPostBackControl(Button1);
}
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = DateTime.Now.ToString();
Label2.Text = DateTime.Now.ToString();
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>
|
コメント †