- PR -

コントロール配列のイベント発生

1
投稿者投稿内容
yunamayu
会議室デビュー日: 2005/03/23
投稿数: 7
投稿日時: 2005-03-24 18:45
Windowsアプリを作製しております。
ボタンを押すと5個のボタンが追加される単純なプログラムですが、新しく発生した
ボタンに対してクリックイベントを発生させる方法がわかりません。
もう少し詳しく説明すると、イベントはEventHandlerをデリゲートするため配列の
パラメータを入れることができません。
初歩的な質問ですが、宜しくお願いします。

private void button1_Click(object sender, System.EventArgs e)
{
for(int i = 0 ; i < 5 ; i++)
{
buttons[i] = new Button();
buttons[i].Size = new Size(50, 50);
buttons[i].Location = new Point(i * 50, 50);
buttons[i].Visible = true;
buttons[i].Text = i.ToString();
buttons[i].Name = i.ToString();
this.Controls.Add(this.buttons[i]);
//this.buttons[i].Click += new System.EventHandler(this.Buttons[i]_Clicked);←こんな風にでればよいのですが?
}
}
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-03-24 19:02
new EventHandlerに渡す引数は、言ってしまえばメソッドの名前です。
つまり基本的に静的、「既にそこにあるもの」を指定する必要があります。

こういう場合、AppendedButton_Clickメソッドなどを作り、
全ての追加されたボタンのClickイベントのイベントハンドラとしてやり、
AppendedButton_Clickメソッドの中でsenderのNameプロパティやTagプロパティなどを使って何が押されたかを判断するようにするのが自然ではないでしょうか。

Buttons1_Clicked, Buttons2_Clicked...メソッドが既にあるのなら、
コード:
EventHandler[] events = new EventHandler[]{
    new EventHandler(this.Buttons1_Clicked), 
    new EventHandler(this.Buttons2_Clicked), ...};
for (int i = 0; i < 5; i++) {
    ...
    buttons[i].Click += events[i];
}

なんて手段もありますが。
yunamayu
会議室デビュー日: 2005/03/23
投稿数: 7
投稿日時: 2005-03-24 19:59
Hongliangさん、早速の回答ありがとうございました。

この方法では、既に5個のボタン(ex:Buttons0〜Buttons4)を用意しておき、
そのクリックイベントを配列として保存しておく。そして、AppendedButton
をクリックすることでそれらのボタンにイベントを発生させる。
と、言う解釈でしょうか?
その場合、例えば配列で作製したボタン(ex:buttons[0]〜buttons[4])と
既設のButtons0〜Buttons4が1対1で対応するということでしょうか?
つまり、buttons[0]をクリックすることでButtons0のイベントが発生する
ということでしょうか?

質問ばかりで申し訳ありません。
もし、私の解釈が正しいなら、配列にする意味がありません。
配列にしたかったのは、配列によりパラメータの一部を修正して同じ動作
をさせるためです。例えば、buttons[0]を押したらTextBox1に「0」、
buttons[1]ならTextBox1に「1」を書き込めればプログラムの行数が
少なくて済みます。

解釈があっていますでしょうか?
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-03-24 20:52
私の投稿は、前半と後半2通りの手段を提示したものです。
例示したコードの影響からか後半のみに着目されたような気がしますし、
yunamayuさんの目的からしてそっちの方が適当な気がしますので、後半部分を解説しましょう。

引用:

この方法では、既に5個のボタン(ex:Buttons0〜Buttons4)を用意しておき、
そのクリックイベントを配列として保存しておく。そして、AppendedButton
をクリックすることでそれらのボタンにイベントを発生させる。
と、言う解釈でしょうか?


いいえ。
私が書いたButtons1_Clickedなどのメソッドは、「自分で書いた」事を前提にしています。
だから別にメソッド名がB1_CでもOnButton01Clickedでも何でも構いません。
とにかくbuttons[i]とevents[i]が対応するようにEventHandlerオブジェクトの配列を作っただけです。
元よりforの中でButtonオブジェクトもnewしてる以上、IDEのデザイナで配置されたボタンをダブルクリックってわけではないのでしょうし。

引用:

その場合、例えば配列で作製したボタン(ex:buttons[0]〜buttons[4])と
既設のButtons0〜Buttons4が1対1で対応するということでしょうか?
つまり、buttons[0]をクリックすることでButtons0のイベントが発生する
ということでしょうか?


ですので、既存のボタンとは何の関係もありません。
buttons[i].Click += の右側でやってる事を先頭に持っていっただけです。

引用:

配列にしたかったのは、配列によりパラメータの一部を修正して同じ動作
をさせるためです。例えば、buttons[0]を押したらTextBox1に「0」、
buttons[1]ならTextBox1に「1」を書き込めればプログラムの行数が
少なくて済みます。


確かにyunamayuさんが考えるほどの省略化はできません。
せいぜい私が先の投稿(の後者)で示したような、
事前にEventHandlerの配列を作ってそれを対応させていくぐらいでしょう。

//リフレクションという手もありますが、この場合余計ややこしくなるだけでしょうし。
にしざき
ぬし
会議室デビュー日: 2003/06/30
投稿数: 304
投稿日時: 2005-03-24 20:53
であるなら、
コード:
private void button1_Click(object sender, System.EventArgs e)
{
  for(int i = 0 ; i < 5 ; i++)
  {
    buttons[i] = new Button();
    buttons[i].Size = new Size(50, 50);
    buttons[i].Location = new Point(i * 50, 50);
    buttons[i].Visible = true;
    buttons[i].Text = i.ToString();
    buttons[i].Name = i.ToString();
    this.Controls.Add(this.buttons[i]);
    this.buttons[i].Click += new System.EventHandler(this.Button_Clicked);
  }
}

private void Button_Clicked(object sender, EventArgs e) {
  Button button = sender as Button;
  if (button != null) {
    // ここで button.Tag を使うなり button を buttons[i] と比較するなりして
    // 押されたボタンを判断
  }
}


yunamayu
会議室デビュー日: 2005/03/23
投稿数: 7
投稿日時: 2005-03-24 23:41
Hongliangさん、再度の回答ありがとうございました。
まだ十分理解してませんが、イベントハンドラの配列を使い
それをメソッド内で処理することと理解しました。

また、にしざきさん、わざわざコードを示して頂きありがとう
ございます。
家のpcには.netがインストールされていませんので、
明日会社で確認致します。
yunamayu
会議室デビュー日: 2005/03/23
投稿数: 7
投稿日時: 2005-03-25 14:57
自己レスです。希望の実装ができました。
サンプルを示します。
private Button[] buttons = new Button[5];
private void button1_Click(object sender, System.EventArgs e)
{
for(int i = 0 ; i < 5 ; i++)
{
Button b=buttons[i] = new Button();
b.Size = new Size(50, 50);
b.Location = new Point(i * 50, 50);
b.Visible = true;
b.Text = i.ToString();
b.Name = i.ToString();
b.Click += new EventHandler(buttons_Click);
this.Controls.Add(b);
}
}

protected void buttons_Click(object sender, EventArgs e)
{
Button b=(Button)sender;
MessageBox.Show(b.Text,b.Name);
}
1

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