2017-05-08 11 views
0

動的に作成されたオブジェクトにEventHandlerをフックしようとしています。このサンプルでは、​​私は単純なウィンドウ.Net TabControlを使用して動的オブジェクトを格納します。簡単にするために、私はButtonとClickイベントを使用します。 主なポイントは、それぞれのタブページをクリックするとの異なる出力を生成する必要があります。動的オブジェクトのC#イベント

public partial class Form1 : Form 
{ 
    int letter = 65; 

    private void simpleButton1_Click(object sender, EventArgs e) 
    { 
     TabPage newPage = new TabPage(); 

     tabControl1.TabPages.Add(newPage); 

     Button btn = new Button(); 

     newPage.Controls.Add(btn); 

     btn.Click += (object s, EventArgs ee) => 
     { 
      // Button on FirstPage should produce "Test A" 
      // Button on SecondPage should produce "Test B" 
      Debug.WriteLine("Test " + (char)letter); 
     }; 

     letter++; 
    } 
} 

ただし、iは任意のページをクリックした方のボタンは、最終ページの出力(すなわち4つのTabPages、すべてのボタンは、「テストD」を生成クリック)を生成します。参照ポインタボタンbtnがすべてのページのボタンのすべてのインスタンスを指しているかのように感じました。

私の仮定:

Button btn = new Button(); 

ボタンの新しいインスタンスへのポインタBTNポイントごとにこの行が実行されないでしょうか?その意味で:

btn.Click += (object s, EventArgs ee) => 

btn.Clickは新しく作成されたButtonのインスタンスのEventHandlerになるはずですか?ポインタbtnがまだボタンのすべてのインスタンスを参照しているかのようです。

この問題について私に教えてください。前もって感謝します。

答えて

1

ラムダ式は、クラスに定義されているletterフィールドへの参照をキャプチャしているため、メソッドは常にその中に格納されている最新の値を使用します。

ボタンを作成するときにletterの値を取得するには、まずintの値をコピーするローカル変数を作成し、ラムダ式のローカル変数を取得します。

// Create a copy of the value 
var character = (char)letter; 

// Now the lambda will capture the local variable 
btn.Click += (object s, EventArgs ee) => 
{ 
    Debug.WriteLine("Test " + character); 
}; 

これは、for loopsと同じ方法で動作します。

を参照してください:あなたは値の型 `letter`を

+0

ありがとう!私はローカル変数の宣言が割り当てられた値をコピーするのを忘れていました。それはうまくいった! – Suwandy

0

変数には1つの値しか格納できません。

あなたはN異なるボタンと N個の異なるイベントハンドラを持っています。

しかし、あなたはフィールドが1つだけletterだから、それらはすべて同じことをします。

代わりに、関数内にローカル変数を作成することができます。各ボタンはclosuresで独自の変数を使用します。

+0

意味ですか? – Suwandy

+0

私が試しているタスクには適していない値型の 'letter'と思われます。 EventHandlerごとに異なる「パラメータ」をどのように割り当てることができますか? 私はPage1を印刷する "Test A"、PageNは "Test N"を印刷します。 プロパティを追加するなど、イベントオブジェクトをカスタマイズする必要はありますか? – Suwandy

+0

@スワンディー:それは値の型とは関係ありません。 – SLaks

関連する問題