2017-05-08 42 views
0

我試圖將EventHandler掛接到動態創建的對象上。在這個示例中,我使用簡單的Windows.Net TabControl來包含動態對象。爲了簡單起見,我使用Button和Click事件。 主要點是按鈕點擊每個TabPage應該產生不同的輸出動態對象上的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++; 
    } 
} 

然而,我點擊任何頁面上取其按鈕產生最後一頁的輸出(即4個TabPage,所有的按鈕點擊產生「測試d」)。它感覺好像參考指針按鈕btn指向每個頁面上的按鈕的所有實例。

我的假設:

Button btn = new Button(); 

不會每次指針BTN指向按鈕的新實例,該行執行?在這個意義上說:

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

btn.Click應該是新創建的Button實例的EventHandler,對不對?看起來好像指針btn仍然指向Button的所有實例。

請在這個問題上給我點啓發。先謝謝你。

回答

1

lambda表達式捕獲對類中定義的letter字段的引用,因此該方法將始終使用存儲在其中的最新值。

要創建按鈕時捕獲letter的值,首先創建一個局部變量以複製int值,然後捕獲lambda表達式中的局部變量。

// 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的工作方式相同。

參見:

+0

非常感謝!我忘了聲明本地變量將複製其分配的值。它運作良好! – Suwandy

0

一個變量只能保存一個值。

你有不同的按鈕和不同的事件處理程序。

但是,您只有一個letter字段,因此它們都執行相同的操作。

相反,你可以在函數內創建一個局部變量;然後,每個按鈕將通過closures使用自己的變量。

+0

你的意思是值類型'letter'? – Suwandy

+0

我看到,似乎值類型'信'不適合我嘗試的任務。我怎樣才能爲每個EventHandler分配不同的「參數」? 我想讓Page1打印「測試A」,PageN打印「測試N」上的按鈕。 我是否需要自定義事件對象,如添加屬性? – Suwandy

+0

@Suwandy:它與值類型無關。 – SLaks