- PR -

動的に追加したテンプレート列にボタンイベントを追加したい

1
投稿者投稿内容
カタナ
大ベテラン
会議室デビュー日: 2006/05/25
投稿数: 110
投稿日時: 2006-11-01 14:11
いつもお世話になります。現在vb.net(vs2003)を用いて開発を行なっています。
私が困っているのはテンプレート列に動的にテキストやボタンを追加して表形式の画面を作ろうと考えています。(縦・横のカラム数は決まっていない)
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=2627&forum=7&4

http://www.microsoft.com/japan/msdn/vs/webapplication/vbtchCreatingWebServerControlTemplatesProgrammatically.aspx#vbtchcreatingwebservercontroltemplatesprogrammaticallyanchor3
を参考にして動的にテンプレート列を追加してテキストにデータバインドしてボタンを表示するところまではできました。
しかしボタンのイベントをどうやって発生させたらいいのかが分かりません。
ボタンを追加する際に、次のようにAddHandlerを入れてはいるのですがイベントに入ってくれません。
AddHandler buttonAdd.Click, AddressOf TemplateControl_Click

動的に作成したテンプレートのボタンイベントを実行する方法を教えてください。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-11-01 22:17
Web アプリですよね?

まず、Page.Load イベントが発生しているか、確認してください。
そして、Page.Load イベントの終了直前に、動的に追加しているはずのテキストやボタンが存在しているか、確認してください。


Web アプリは、Win アプリと違って、サーバ コードが走るときには毎回新しいオブジェクトが作成されます。以前あったからといって、今回もあるとは限りません。
_________________
カタナ
大ベテラン
会議室デビュー日: 2006/05/25
投稿数: 110
投稿日時: 2006-11-02 11:33
jittaさん返信ありがとうございます。
申し訳ありません。記述が足りませんでした。webアプリです。

page.loadイベントは発生しています。またテキストやボタンも作成されています。
ただボタンに設定したはずのCommandNameが設定されていません。
AddHandlerがうまいこといかないのでItemCommandイベントでCommandNameごとに処理をしようとしているのですが・・・。
動的に作成したテンプレートのボタンイベントってとれるのでしょうか?
ほとほと困っています。

以上 よろしくお願いします。
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2006-11-02 12:11
「動的にテンプレート列を追加」をPage_LoadではなくPage_Initで行うとよいかも。

[ メッセージ編集済み 編集者: todo 編集日時 2006-11-02 16:20 ]
未記入
ベテラン
会議室デビュー日: 2003/06/26
投稿数: 76
投稿日時: 2006-11-02 16:31
動的に追加したボタンのonClickイベントで、動的に追加していないボタンを押下するJavaScriptを記述する方法は?
必要ならばパラメタもhidden項目にセットするようにしては?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-11-02 21:52
 Web アプリでは、サーバ コードが実行されるごとに、毎回オブジェクトが作られます。
このため、AddHandler をしても、次にサーバ コードが実行されるときには、そのオブジェクトはありません。

 で、どうするかというと、CommandName です。これを設定しておくと、Itemcommand イベントが発生します。このイベントで、CommandName を見て、処理を振り分けます。

……ここまでは ok ですね。

 で、次。Web アプリケーションでは、サーバ コードが実行されるごとに、毎回オブジェクトが作られます。
何度も繰り返すのは、とても重要で、絶対に憶えておいて欲しいことだからです。

 毎回新しく作られるなら、「状態が変わった」というイベントは発生させられません。これは、分かりますか?ボタンのクリックも、ボタンが「押されていない状態」から、「押されている状態」(そして、離された状態)へ変化したから発生するものです。
このため、「前回のサーバ コード実行時の状態」を、どこかに保存しておく必要があります。その一つが ViewState です。
 端折りますが、クライアントからの要求を受け付けると、ViewState からコントロール情報を復元し、「前回のサーバ コード実行時の状態」を復元した上で、Page.Load イベントが発生します。ボタン クリックなどのイベントは、この後に発生します。
したがって、Page.Load で、「前回の…状態」を潰してしまうと、イベントを発生させるための情報も無くなってしまい、イベントが発生しなくなります。(todoさんのアドバイス)


 ViewState が無効になっていませんか?DataGrid の ViewState を有効にしてみてください。
 Page.Load の中で DataBind を行っていませんか?その部分を IsPostBack を見て、True ならば通らないようにしてみてください。

_________________
カタナ
大ベテラン
会議室デビュー日: 2006/05/25
投稿数: 110
投稿日時: 2006-11-06 10:51
Jittaさん、ぜうすさん、todoさん返信ありがとうございます。また返信が遅れて申し訳ありません。

jittaさん>ViewState が無効になっていませんか?
はい。無効になっていません。
jittaさん>Page.Load の中で DataBind を行っていませんか?その部分を IsPostBack を見て、True ならば通らないようにしてみてください
そのようになっているとは思うのですが・・・。

長くなって申し訳ありませんがテスト的に作成したソースを転記します。左に列を追加ボタンを押しても DataGrid1_ItemCommandイベントが発生しません。悪い箇所を指摘して頂けると大変ありがたいのですが・・・。以上 よろしくお願い致します。

----------------------------------------------------------------
☆webフォーム
Public Class WebForm1
Inherits System.Web.UI.Page


Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack = True Then
'テンプレート列1
Dim tc1 As New TemplateColumn
tc1.HeaderTemplate = New _
DataGridTemplate(ListItemType.Header, "Column1")
tc1.ItemTemplate = New DataGridTemplate(ListItemType.Item, "Column1")
tc1.EditItemTemplate = New _
DataGridTemplate(ListItemType.EditItem, "Column1")
tc1.FooterTemplate = New _
DataGridTemplate(ListItemType.Footer, "Column1")
DataGrid1.Columns.Add(tc1)

'テンプレート列2
Dim tc2 As New TemplateColumn
tc2.HeaderTemplate = New _
DataGridTemplate(ListItemType.Header, "Column2")
tc2.ItemTemplate = New DataGridTemplate(ListItemType.Item, "Column2")
tc2.EditItemTemplate = New _
DataGridTemplate(ListItemType.EditItem, "Column2")
tc2.FooterTemplate = New _
DataGridTemplate(ListItemType.Footer, "Column2")
DataGrid1.Columns.Add(tc2)

Dim TempHeader As New TemplateHeadDb
TempHeader.GetTemplateHeader("42", Me.DataSet1)  'ここでデータをデータを取得
ViewState("DataSet") = Me.DataSet1
DataGrid1.DataSource = Me.DataSet1
DataGrid1.DataBind()
End If
End Sub
↓☆ここに入らない
Private Sub DataGrid1_ItemCommand(ByVal source As Object, ByVal e As System.Web.UI.WebControls.DataGridCommandEventArgs) Handles DataGrid1.ItemCommand

End Sub
End Class

----------------------------------------------------------------
☆テンプレートクラス
Public Class DataGridTemplate
Implements ITemplate

Dim templateType As ListItemType
Dim columnName As String

Sub New(ByVal type As ListItemType, ByVal ColName As String)
templateType = type
columnName = ColName
End Sub

Sub InstantiateIn(ByVal container As Control) Implements ITemplate.InstantiateIn
Dim lc As New Literal

Select Case templateType
Case ListItemType.Header ' ヘッダ
Dim PlaceHolder As PlaceHolder = New PlaceHolder
lc.Text = "<B>" & columnName & "</B>"
PlaceHolder.Controls.Add(lc)
container.Controls.Add(PlaceHolder)
Case ListItemType.Item ' アイテム表示
Dim PlaceHolder As PlaceHolder = New PlaceHolder
Dim buttonAdd As New System.Web.UI.WebControls.Button
buttonAdd.Text = "左に列を追加"
buttonAdd.CommandName = "NextMeisai" ←☆ここでCommandNameをセットしている
PlaceHolder.Controls.Add(buttonAdd) '追加ボタン

lc.Text = columnName
PlaceHolder.Controls.Add(lc)
container.Controls.Add(PlaceHolder)


Case ListItemType.EditItem ' 編集
Dim tb As New TextBox
tb.Text = columnName
container.Controls.Add(tb)
Case ListItemType.Footer ' フッタ
Dim tb As New TextBox
tb.Text = ""
container.Controls.Add(tb)
End Select
End Sub

Private Sub TemplateControl_DataBinding(ByVal sender As Object, ByVal e As System.EventArgs)
Dim lc As Literal
lc = CType(sender, Literal)
Dim container As RepeaterItem
container = CType(lc.NamingContainer, RepeaterItem)
lc.Text &= DataBinder.Eval(container.DataItem, "CategoryName")
lc.Text &= "</TD></TR>"
End Sub

End Class
1

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