- PR -

動的に作成したボタンのイベントハンドラの関連付け

1
投稿者投稿内容
GALOAD
会議室デビュー日: 2006/07/27
投稿数: 10
投稿日時: 2006-08-17 20:26
ASP.NET2.0の「コントロール配列」に関して、2点ほど悩んでいる事があります。
どうか皆さんの知恵を貸していただけますようお願い致します。


画面をロード時に、画面の上部と下部に「検索」、「クリア」、「前画面へ」ボタンを
コントロール配列にて動的に作成するようなウェブ画面を作っています。

この画面を動かした結果、画面の表示までは正常に動作するのですが、
ボタンを押された際のイベントハンドラの関連付けを、
下記のソースの19行、30行、41行のように記述しているつもりなのですが、
ボタンをクリックしてみても、
指定したイベント(btnKensaku_Click、btnClear_Click、btnBack_Clickプロシージャ)を
通ることなく、ポストバックされてしまいます。

(質問1)
うまく動作しない原因は、イベントハンドラの関連付けに間違があるものだと
思っているのですが、19行、30行、41行の記述ではだめなのでしょうか?


(質問2)
ポストバックした際、画面ロード時に生成したボタンが消えてしまうのですが、
ポストバックした後でも、ボタンを表示しておく方法はないでしょうか?


01:<%@ Page Language="VB" %>
02:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
03:
04:<script runat="server">
05: Protected Sub Page_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
06: Dim ii As Integer
07: Dim btn(2) As Button
08:
09: If Not IsPostBack Then
10: '-----------------------------------------------
11: ' 画面の上部と下部にボタン設置
12: '-----------------------------------------------
13: '// 「検索」ボタン作成
14: For ii = 0 To 1
15: btn(ii) = New Button()
16: btn(ii).ID = "btnNext"
17: btn(ii).Text = "検  索"
18: btn(ii).Attributes.Add("class", "BTN_MAIN")
19: AddHandler btn(ii).Click, AddressOf btnKensaku_Click
20: Next
21: PnlHeader.Controls.Add(btn(0)) '上部に設置
22: PnlFooter.Controls.Add(btn(1)) '下部に設置
23:
24: '// 「クリア」ボタン作成
25: For ii = 0 To 1
26: btn(ii) = New Button()
27: btn(ii).ID = "btnClear"
28: btn(ii).Text = "クリア"
29: btn(ii).Attributes.Add("class", "BTN_MAIN")
30: AddHandler btn(ii).Click, AddressOf btnClear_Click
31: Next
32: PnlHeader.Controls.Add(btn(0)) '上部に設置
33: PnlFooter.Controls.Add(btn(1)) '下部に設置
34:
35: '// 「前画面へ」ボタン作成
36: For ii = 0 To 1
37: btn(ii) = New Button()
38: btn(ii).ID = "btnBack"
39: btn(ii).Text = "前画面へ"
40: btn(ii).Attributes.Add("class", "BTN_MAIN")
41: AddHandler btn(ii).Click, AddressOf btnBack_Click
42: Next
43: PnlHeader.Controls.Add(btn(0)) '上部に設置
44: PnlFooter.Controls.Add(btn(1)) '下部に設置
45: End If
46: End Sub
47:
48: '「検索」ボタンクリック時のイベント
49: Sub btnKensaku_Click(ByVal sender As System.Object, ByVal e As EventArgs)
50: Server.Transfer("KENSAKU_DISP.aspx")
51: End Sub
52:
53: Sub btnClear_Click(ByVal sender As System.Object, ByVal e As EventArgs)
54: koumoku1.Text = ""
55: koumoku2.Text = ""
56: koumoku3.Text = ""
〜(途中省略)〜
58: koumoku97.Text = ""
59: koumoku98.Text = ""
60: koumoku99.Text = ""
61: End Sub
62:
63: '「前画面へ」ボタンクリック時のイベント
64: Sub btnBack_Click(ByVal sender As System.Object, ByVal e As EventArgs)
65: Server.Transfer("BACK_DISP.aspx")
66: End Sub
67:</script>
68:
69:<html xmlns="http://www.w3.org/1999/xhtml" >
70:<head runat="server">
71: <title>無題のページ</title>
72:</head>
73:<body>
74: <form id="form1" runat="server">
75: <div>
76: <asp:Panel ID="PnlHeader" runat="server" Height="30px" Width="500px"
/>
77: <table border="1">
78: <tr><td>検索項目1:</td><td><asp:TextBox ID="koumoku1" Columns="50" runat="server"/></td></tr>
79: <tr><td>検索項目2:</td><td><asp:TextBox ID="koumoku2" Columns="50" runat="server"/></td></tr>
80: <tr><td>検索項目3:</td><td><asp:TextBox ID="koumoku3" Columns="50" runat="server"/></td></tr>
〜(途中省略)〜
82: <tr><td>検索項目97:</td><td><asp:TextBox ID="koumoku97" Columns="50" runat="server"/></td></tr>
83: <tr><td>検索項目98:</td><td><asp:TextBox ID="koumoku98" Columns="50" runat="server"/></td></tr>
84: <tr><td>検索項目99:</td><td><asp:TextBox ID="koumoku99" Columns="50" runat="server"/></td></tr>
85: </table>
86: <asp:Panel ID="PnlFooter" runat="server" Height="30px" Width="500px" />
87: </div>
88: </form>
89:</body>
90:</html>
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-08-17 21:02
引用:
(質問1)
うまく動作しない原因は、イベントハンドラの関連付けに間違があるものだと
思っているのですが、19行、30行、41行の記述ではだめなのでしょうか?

If Not IsPostBack Then
の中で書いてあるのですから初回しか関連付けられませんよね。

引用:
(質問2)
ポストバックした際、画面ロード時に生成したボタンが消えてしまうのですが、
ポストバックした後でも、ボタンを表示しておく方法はないでしょうか?

理由は(質問1)と同じです。「消えてしまう」ではなく「作られなかった」と考えるべきです。

ボタン押下時のPageインスタンスは初回のPageインスタンスとは別ですから。
GALOAD
会議室デビュー日: 2006/07/27
投稿数: 10
投稿日時: 2006-08-17 22:56
べる様

早速の返事、誠にありがとうございました。

それから、If Not IsPostBack Then の判定を削除しました。
しかし、画面表示後に生成されたボタンを押すと、下記のようなエラー画面が表示されます。

=====↓↓↓↓↓ 以下、エラー画面の内容 ↓↓↓↓↓=====

同じ ID 'btnNext' を含む複数のコントロールが見つかりました。FindControl を使うには、コントロールに一意の ID を指定する必要があります。
説明: 現在の Web 要求を実行中に、ハンドルされていない例外が発生しました。エラーに関する詳細および例外の発生場所については、スタック トレースを参照してください。

例外の詳細: System.Web.HttpException: 同じ ID 'btnNext' を含む複数のコントロールが見つかりました。FindControl を使うには、コントロールに一意の ID を指定する必要があります。

ソース エラー:

現在の Web 要求の実行中にハンドルされていない例外が生成されました。障害の原因および発生場所に関する情報については、下の例外スタック トレースを使って確認できます。

スタック トレース:


[HttpException (0x80004005): 同じ ID 'btnNext' を含む複数のコントロールが見つかりました。FindControl を使うには、コントロールに一意の ID を指定する必要があります。]
System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls) +268
System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls) +340
System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls) +340
System.Web.UI.Control.EnsureNamedControlsTable() +77
System.Web.UI.Control.FindControl(String id, Int32 pathOffset) +179
System.Web.UI.Page.FindControl(String id) +57
System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +282
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3321




--------------------------------------------------------------------------------
バージョン情報: Microsoft .NET Framework バージョン:2.0.50727.42; ASP.NET バージョン:2.0.50727.42

=====↑↑↑↑↑ ここまで ↑↑↑↑↑=====

私の理解不足でもしかしたら、If Not IsPostBack Thenの条件をはずすだけでは
駄目なのでしょうか?(本当に初心者的な疑問で申し訳ありません)

よろしくお願い致します。

[ メッセージ編集済み 編集者: GALOAD 編集日時 2006-08-17 22:57 ]
べる
ぬし
会議室デビュー日: 2003/09/20
投稿数: 1093
投稿日時: 2006-08-18 00:59
引用:
同じ ID 'btnNext' を含む複数のコントロールが見つかりました。

エラーの言っている通りです。If Not IsPostBack Then を外したのが根本原因ではありません。
そのコードだとbtnNext、btnClear、btnBackというIDを持つコントロールがそれぞれ二つできてしまいますよね。
別のIDにしてみては同でしょうか。(ハンドルするメソッドは同じでよい)
「FindControl を使うには」といっているのは、内部的にどこかで使われているのでしょうね。
GALOAD
会議室デビュー日: 2006/07/27
投稿数: 10
投稿日時: 2006-08-18 02:33
べる様

お世話になっております。

アドバイス頂きました通り、IDを別名にする事で解決しました。
(改めて考えてみると今回、ID名を同じにする必要もありませんでした)

13:'// 「検索」ボタン作成
14:For ii = 0 To 1
15:btn(ii) = New Button()
16:btn(ii).ID = "btnNext" & CStr(ii)
17:btn(ii).Text = "検  索"
18:btn(ii).Attributes.Add("class", "BTN_MAIN")
19:AddHandler btn(ii).Click, AddressOf btnClear_Click
20:btn(ii).CommandName = CStr(ii)
21:Next
22:PnlHeader.Controls.Add(btn(0)) '上部に設置
23:PnlFooter.Controls.Add(btn(1)) '下部に設置

以上のような「ID="ボタンID" & ループインデックス」でIDをセットし、
20行目でボタン押された際、上下どちらのボタンが押されたか
判断つくようにしました。

お陰様で、何とか形になりました。
ご指摘・助言を賜り、誠にありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)