2013-12-09 136 views
2

我需要有人來幫助我解決這個小問題。下面是一個代碼片段:拉姆達表達事件

void shuffle() 
{ 
    for (int i = 0; i < 4; i++) { 

     // here should be the computations of x and y 

     buttons[i].Click += (s, e) => { show_coordinates(x, y); }; 

     // shuffling going on 
    } 
} 

void show_coordinates(int x, int y) 
{ 
    MessageBox.Show(x + " " + y); 
} 

,你可以看到我創建具有不同X和Y一個新的事件處理程序,每個按鈕每次運行循環時間。我的表單中還有另一個按鈕,隨機混合按鈕。

所以,這裏是問題:如果我按下shuffle按鈕說10次,然後按任何混洗按鈕,事件處理程序堆積起來,我得到10個消息框顯示x和y值。

那麼我怎麼能每次按shuffle覆蓋以前的事件處理程序與新的事件處理程序。

在此先感謝。

+0

看起來這不會編譯爲'x'和'y'不會在拉姆達構造的點存在。 – asawyer

+0

確實如此,然而編譯器可能會告訴他::) 正如他寫的,當他點擊它時,他已經設法獲得了10次結果。我們可以期望他只是省略了那個特定的代碼。 – woutervs

回答

7

我會重新設計的代碼,而不是做這樣的事情:

private PointF[] points = new PointF[4]; 

//Run once 
public void Initialize() 
{ 
    for (int i = 0; i < 4; i++) 
     buttons[i].Click += (s, e) => { show_coordinates(i); }; 
} 

public void Shuffle() 
{ 
    for (int i = 0; i < 4; i++) 
    { 
     // here should be the computations of x and y 
     points[i] = new PointF(x,y); 
     // shuffling going on 
    } 
} 

public void show_coordinates(int index) 
{ 
    var point = points[index]; 
    MessageBox.Show(point.X + " " + point.Y); 
} 
+0

獨立使用類很好用。請注意,不清除事件處理程序會導致內存泄漏(至少在Winforms中我遇到過這種對象句柄的形式) – Mino

0

反射是一種方法來做到這一點,但我更喜歡委託並添加/刪除該委託。這導致更容易維護的代碼比使用反射:

How to remove a lambda event handler

+0

你提到刪除代表。但是它會在這種特殊情況下發揮作用嗎?我是否必須創建一個數組來保存每個按鈕的代理? – Linas

+0

繼承人使用委託的一個很好的例子http://msdn.microsoft.com/en-us/library/ms173172.aspx – Mino

0

在你的for循環首先刪除事件處理程序,然後重新添加。然而,考慮到這是不好的做法。你應該使用按鈕的datacontext並將一個對象綁定到包含你的x和y值的對象。 這樣你只需要附加你的事件處理程序一次。而不是每次洗牌被調用。然後更新你的按鈕datacontext是更方便。

Example PseudoCode: 
public MainWindow() { 
ForEach Button addEvent(DoSomething); 
ForEach Button Button.Datacontext = new Data(); 
} 

public class Data { 
prop X; 
prop Y; 
ctor(x,y) 
ctor() 
} 

public void DoSomething() 
{ 
var data = Button.datacontext as data 
MessageBox(data.x, data.y) 
} 

public void Shuffle() 
{ 
calc x, y 
foreach Button (Button.datacontext as data).x = x, ... 
} 
+0

DataContext是一個WPF thingy,問題被標記爲WinForms。 – Maarten

+0

完全查看,在winforms而不是datacontext中,可以使用標記(如果這是一個字符串,則標記與字典結合) – woutervs

+0

標記可以是任何東西,Tag屬性是Object類型。 – Maarten