• 締切済み

動的に生成したボタンのイベントが拾えない

環境は、Visual Web Developer 2008 Express Editon with C# です。 データベースは、Oracle 10g Express Edition です。 触り始めて、1週間程度ですので、お手やらかに。 次のようなコードで、Oracleから取得した値をテーブルに表示しています。ここでreaderは、System.Data.OracleClient.OracleDataReaderラスのオブジェクト、Menuは、System.Web.UI.WebControls.Tableクラスのオブジェクトです。 while (reader.Read()) {   object[] values = new object[3];   int i = reader.GetOracleValues(values);   TableRow r = new TableRow();   TableCell delcom = new TableCell();   Button delButton = new Button();   delButton.Click += new EventHandler(delButton_Click);   delButton.Text = "削除";   delcom.Controls.Add(delButton);   r.Cells.Add(delcom);   for (int j = 0; j < 3; j++)   {     TableCell cell = new TableCell();     cell.Text = values[j].ToString();     r.Cells.Add(cell);   }   Menu.Rows.Add(r); } このコードは、メソッドにして、Page_Loadおよび、delButton_Clickの両メソッドから呼び出しています。 ここで、各行に貼り付けた「削除」ボタンを押すと、1回目では削除されず、2回目で削除されるという現象が起きています。 デバッガで追うと、1回目はdelButton_Clickメソッドが呼ばれず、2回目では呼ばれています。 1回目の表示では、設定したイベントが 色々、調べてみましたが、ちょっとお手上げです。 どのようにすれば、毎回この設定したイベントが有効になるかお知恵を拝借できないでしょうか? よろしくお願いします。

みんなの回答

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

当方 VS2005なのですが 動的に作成したボタンイベントも1回目でハンドラへ来ますよ 当方で実験したコードは以下のような感じです データベースを使わずに 無条件で10個のボタンを作成します PageのViewStateを使って表示/非表示を切り替えます protected void Page_Load(object sender, EventArgs e) {   for (int n = 0; n < 10; n++)   {     TableRow r = new TableRow();     TableCell c = new TableCell();     Button btn;     string ss = String.Format("del{0,2:d}", n);     btn = new Button();     btn.Text = ss;     btn.Font.Name = Table1.Font.Name;     btn.Font.Size = Table1.Font.Size;     btn.Click += new EventHandler(myClick);     if (IsPostBack && !ViewState.IsItemDirty(ss))     {       // ポストバック時にViewStateにアイテムが無いなら非表示       btn.Visible = false;       c.Visible = false;       r.Visible = false;     }     c.Controls.Add(btn);     r.Controls.Add(c);     Table1.Controls.Add(r);     if (!IsPostBack)     {       // 初回のみViewStateに登録       ViewState[ss] = ss;     }   } } protected void myClick(object sender, EventArgs e) {   Button btn = (Button)sender;   // ViewStateからアイテムを削除   ViewState.Remove(btn.Text);   // コントロールを削除   Table1.Controls.Remove(btn.Parent.Parent); } といった具合です PageLoad時に ViewStateを見てコントロールの作成自体をスキップするコードにすると Clickイベントの引数senderがおかしくなる現象が起きました たとえば 3番目の『del 2』を削除した後『del 3』を削除しようとした場合『del 4』を削除してしまいます ここでもう一度『del 3』をクリックすると『del 3』が削除される といった現象です GridViewを使ったほうが簡単に実現出来そうですよ

masa6272
質問者

お礼

やはり、無理でした。 リンクの生成のタイミングですね。 何か、うまい方法を考えます。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

データベースを介さずに単純に ボタンだけを動的に生成した場合は 『delButton_Click』への到達は1回目で可能なのか確かめましょう

関連するQ&A

  • vb.net web 動的に作成したTableが消える

    よろしくお願いします 現在、vs.net 2005 で web ページを作成しています そこで質問があるので、ご教授の程よろしくお願いします。 test.aspx Table コントロール配置:Table1 Button コントロール配置:Button1 Label コントロール配置:Label1 Label コントロール配置:Label2 test.aspx.vb Partial Class test Inherits System.Web.UI.Page Protected Sub form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles form1.Load Dim row As TableRow Dim col As TableCell If (Page.IsPostBack = False) Then Label2.Text = "aaa" row = New TableRow col = New TableCell : col.Text = "行0:列0" : row.Cells.Add(col) : col = Nothing col = New TableCell : col.Text = "行0:列1" : row.Cells.Add(col) : col = Nothing Table1.Rows.Add(row) row = New TableRow col = New TableCell : col.Text = "行0:列0" : row.Cells.Add(col) : col = Nothing col = New TableCell : col.Text = "行0:列1" : row.Cells.Add(col) : col = Nothing Table1.Rows.Add(row) End If End Sub Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click Label1.Text = "Rows.Count" & Table1.Rows.Count End Sub End Class ボタンを押すと、 Label2の "aaa" は保持されていて Table1が保持されないのはなぜなのでしょうか? Table1 の内容を保持させたいのですが その場合、どのようにすればよいのでしょうか

  • GridViewにバインドせずにデータを表示する方法

    環境:VS2008&VB.NET&ASP GridViewに手動でテーブルからデータを読みデータバインドせず DBの値を表示する方法を考えていますがうまくいかず困っています。 (データバインドしたくない理由はデータバインドを行っていると行の挿入や移動ができない認識のためです。) 初心者のため見当違いなことをしているかもしれませんが それも含めまして質問させていただきます。 質問1 そもそもGridViewでデータバインドせずに手動でデータを表示することは可能でしょうか。 質問2 以下のコードで試しましたが「GridView1.Controls(0).Controls.Add(row1)」でExeptionが発生してしまいました。 手順に不適格な箇所があるのでしょうか。 strSql = "SELECT * FROM Data_Table" Using connection As New SqlClient.SqlConnection(cnStr) Dim command As New SqlClient.SqlCommand(strSql, connection) connection.Open() Dim dr As SqlClient.SqlDataReader = command.ExecuteReader While (dr.Read = True) 'データあり str1 = dr("data1") str2 = dr("data2") str3 = dr("data3") End If connection.Close() Dim item1 As DataGridItem item1 = New DataGridItem(-1, -1, ListItemType.Item) Dim cell0 As TableCell = New TableCell item1.Cells.Add(cell0) Dim cell1 As TableCell = New TableCell item1.Cells.Add(cell1) Dim cell2 As TableCell = New TableCell item1.Cells.Add(cell2) Dim row1 As New GridViewRow(-1, -1, DataControlRowType.Header, DataControlRowState.Normal) row1.Cells.Add(cell0) row1.Cells.Add(cell1) row1.Cells.Add(cell2) GridView1.Controls(0).Controls.Add(row1) End While End Using エラーの内容 System.ArgumentOutOfRangeException はユーザー コードによってハンドルされませんでした。 Message="指定された引数は、有効な値の範囲内にありません。 パラメータ名: index" お力添えをよろしくお願い致します。

  • swingのラジオボタンについて

    たびたびすみません!! (1)ラジオボタンのアクションをどのように渡したらよいでしょうか? fontcolorActionをどこかにadd()しなければなりませんが group.add(fontcolorAction); button1.add(fontcolorAction); どちらもできません(泣 (2)setForeground()を使うと全部の文字の色が変換されてしまいます。選択した文字列の色や文字の大きさだけ変換するメソッドなどもないでしょうか?? (3)getContentPane().setBackground(Color.WHITE);を使うと表示されるウィンドウの中身が白色になると思うんですが薄紫色のままです。どうしたらよいでしょうか? public class NotePad3 extends JFrame { JDesktopPane desktop; JTextArea editArea = new JTextArea(); ButtonGroup group = new ButtonGroup(); JRadioButton button1 = new JRadioButton("black"); JRadioButton button2 = new JRadioButton("blue"); public static void main(String[] args){ NotePad3 frame = new NotePad3(); frame.setVisible(true); } public NotePad3(){ desktop = new JDesktopPane(); FontColorAction fontcolorAction = new FontColorAction(); JMenuBar mb = new JMenuBar(); JMenu sub11 = new JMenu("色"); group.add(button1); group.add(button2); sub11.add(button1); sub11.add(button2); getContentPane().add(desktop,BorderLayout.CENTER); getContentPane().setBackground(Color.WHITE); } class FontColorAction extends AbstractAction{ FontColorAction(){ } public void actionPerformed(ActionEvent e){ NoteFrame inframe = (NoteFrame)desktop.getSelectedFrame(); JTextArea ta = inframe.getTextArea(); if(e.getSource() == button1){ ta.setForeground(Color.black); }else if(e.getSource() == button2){ ta.setForeground(Color.blue); } } }

    • ベストアンサー
    • Java
  • カレンダーを作っているのですが

    import java.awt.*; import java.awt.event.*; public class GraphicsC4 extends Frame { public static void main(String ar[]){ Frame f=new GraphicsC4(); f.setTitle ("平成19年6月 (GridLayout)"); f.setSize(640,400); f.setVisible(true); } GraphicsC4(){ setFont(new Font("SansSerif",Font.BOLD+Font.ITALIC,30)); GridLayout gl=new GridLayout(6,7); setLayout(gl); String day[]={"SUN","MON","TUE","WED","THU","FRI","SAT"}; for(int j=0;j<=6;j++){ Button b1=new Button(day[j]); add(b1); } for(int e=1;e<=5;e++){ Button b2=new Button(""); add(b2); } for(int i=1;i<=30;i++){ Button b3=new Button(""+i+""); add(b3); } addWindowListener(new WinAdapter()); } class WinAdapter extends WindowAdapter{ public void windowClosing(WindowEvent we){System.exit(0);} } } ここまで書いたのですが、日曜日を赤く表示することが出来ません。どなたか教えてください。

  • JButtonの配置

    FlowLayoutによって、JFrameにボタン6個を2×3に配列するプログラムを考えています。ボタンを配置することはできたのですが、ウインドウの大きさを変えるとボタンが3×2になったりと変更してしまいます。 ウインドウの大きさを変えても、ボタンの大きさは変えず、ボタン6個が2×3配列になるプログラムはどうしたらよいのでしょうか?以下は、途中のプログラムです。 import java.awt.*; import javax.swing.*; public class sample { public static void main(String[] args){ MyFrame frame = new MyFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } public class MyFrame extends JFrame { public static final int WIDTH = 200; public static final int HEIGHT = 300; public MyFrame(){ setSize(WIDTH,HEIGHT); Container contentPane = getContentPane(); MyPanel panel = new MyPanel(); contentPane.add(panel); } } public class MyPanel extends JPanel{ public static final int MESSAGE_X = 200; public static final int MESSAGE_Y = 200; setLayout(new FlowLayout()); JButton button1 = new JButton("Button1"); contentPane.add(button1); JButton button2 = new JButton("Button2"); contentPane.add(button2); JButton button3 = new JButton("Button3"); contentPane.add(button3); JButton button4 = new JButton("Button4"); contentPane.add(button4); JButton button5 = new JButton("Button5"); contentPane.add(button5); JButton button6 = new JButton("Button6"); contentPane.add(button6); }

    • ベストアンサー
    • Java
  • クラスメソッドのみのクラスのオブジェクト生成は不可??

    あるテキストのjavaの問題です。 public class Draw{   static void pixel(int x,int y){     /*座標(x、y)に点を描画*/   }   static void line(int x1,int y1,int x2,int y2){     /*座標(x1、y1)~(x2、y2)に線を引く*/   } } で、これを実行するための以下のようなクラス public class TestDraw{ <ここに入力> } という問題なのですが2つまでは絞れたのですが、 (1) public static void main(String args[]){   Draw d = new Draw().line(10,10,20,30); } ↑× (2) public static void main(String args[]){   Draw.line(10,10,20,30); } ↑○ (2)はlineメソッドがstaticメソッドだからオブジェクト生成しなくても良い、ということなんですが (1)も正解のような気がするのですが・・・ 解説によると「lineはvoidなのでnew Draw().line(10,10,20,30);とすれば正解、とあります。 どうもいまいち理解できません。 クラスメソッドはオブジェクト生成しなくとも良い→オブジェクト生成できない ということなのでしょうか? それからちなみに、public classって2つ記述できないんではありませんでしたか?

    • ベストアンサー
    • Java
  • プログラミングで困っています。

    メインメソッドで、 MyArray array = new MyArray(10); // サイズ10の配列をつくります。 を実行したとします。クラス MyArrayは配列にObjectを挿入、削除できるメソッド(add()とdelete())、+その他を追加したものです。 MyArrayクラスの中から、arrayを他のクラスに返すメソッドを作ることはできるんでしょうか?arrayの配列だけを返すのでなくて、MyArrayであるarrayそのものを返したいのですが、どうすればいいでしょうか。 理由は、他のメソッドから、arrayの配列に行われたadd()とdelete()の回数をモニターする必要があるからです。 *add()とdelete()には、呼ばれるたびに、int counterを1ずつ増やすようにしています。counterの数の変化によってarray配列が変化したかどうかモニターするわけです。

  • オブジェクト生成についての疑問

    ------------------- | Button1 Button2 | ------------------- |   CardLayout   | ------------------- CardLayoutはUP1(UnderPanel)とUP2を重ねて配置。 というレイアウトにした場合、 Button1でカード1(UP1)、Button2でカード2(UP2) を表示させたいのですがその際 public void set1(){ //パネル1へラベル配置 UP1.removeAll(); UP1.add(new JLabel("L1")); } public void setU2(){ //パネル2へラベル配置 UP2.removeAll(); UP2.add(new JLabel("L2")); } public void actionPerformed(ActionEvent e){ if(e.getSource() == B1){ //Button1ならカード1 set1(); CL.show(UP, "u1"); } else if(e.getSource() == B2){ //Button2ならカード2 set2(); CL.show(UP, "u2"); } cp.repaint(); } } ********************** JLabel L1, L2 とはせずにカードが変更される都度JLabelを生成するようにしたいのですが、上記では B1→B2→B1→…と交互に押す分には問題ないのですが、B1→B1と同じボタンを連続して押すと、cp.repaint()でカード内のオブジェクトが消えてしまいます。 なぜこのような現象が起きてしまうのでしょうか?

    • ベストアンサー
    • Java
  • getInsets() メソッドの使い方について

    JAVA言語を勉強中の者です getInsets() メソッドでフレームの外周に空白部分を 作るのですが、その場合は以下のように   public Insets getInsets(){     return new Insets(40,10,10,10);   } とオーバーライドするとあります。 オーバーライドのみで外周に空白ができるのを確認できたのですが このオーバーライドされたメソッドをフレームのコンストラクター内等でgetInsets(); とメソッドを書かなければ, このメソッドはフレームに反映されなのではないかと考えているのですが、 実際は書かなくても外周の空白はきっちりととれます。 どうしてオーバーライドのみでこのメソッドは実行結果に反映されるのでしょうか。 よろしくお願いします   MyFrame(String ss){     .............     getInsets(); //この記述不要で動作します     .............   } 簡単なソースを記述しました import java.awt.*; public class Sample{   public static void main(String args[]){     MyFrame frame = new MyFrame("Sample.java");     frame.setSize(200,200);     frame.setVisible(true);   } } class MyFrame extends Frame{   Button b1, b2, b3, b4;   MyFrame(String ss){     super(ss);     setLocation(100,100);     setLayout(new GridLayout(2,2));     //getInsets(); この記述がないと外周空白はできないと考えています     add(b1=new Button("1"));     add(b2=new Button("2"));     add(b3=new Button("3"));     add(b4=new Button("4"));   }   public Insets getInsets(){     return new Insets(40,10,10,10);   } }

    • ベストアンサー
    • Java
  • IteratorとConcurrentModificationException

    IteratorにConcurrentModificationExceptionをthrowさせるやり方がわかりません。 配列に数字を挿入、削除するクラスをつくりました。 MyArrayにあるメソッド、変数 int [] array int mod // 挿入、削除の合計回数 初期値は0 add(int n) // nをarrayに挿入します delete() // 一番うしろの数字を削除します getMod() // modを返します iterator() // new ArrayIterator (array.length, mod) を返します。 modはadd()とdelete()が呼ばれるたびに1ずつ増えていくようにしています。ArrayIteratorはIteratorをimplementsしたクラスです。 <メインメソッドのコード> MyArray a = new MyArray (10); // サイズが10の配列をつくります a.add(1); a.add(2); a.add(3); a.add(4); Iterator it = a.iterator(); it.next(); // 配列の一番最初の数字を返します。 (i.e. 1) a.add(5); // 5を配列に挿入します。 // Iterator以外のメソッドで配列を変えてしまったので、 // ConcurrentModificationExceptionをthrowさせたいんです。 it.next(); // ここでConcurrentModificationExceptionをthrowしてくれません add()、 delete()、 getMod()はそのままにして全く変えずに、これができる方法ありますか?(その三つのメソッド以外は書きかえれます)it.next()だけでなく、it.hasNext()、it.remove()でも同じようにConcurrentModificationExceptionがthrowされるようにしたいのですが・・・。

専門家に質問してみよう