2013-12-09 141 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