在 EventHandler 中向方法传递参数

5
这个问题已经被问了很多次,但是解决方案因某些原因无法正常工作。
我正在动态创建一个按钮并为其分配一个事件处理程序。
protected void Page_Load (object sender, EventArgs e)
{
    Button b = new Button();
    b.Click += new EventHandler(Method);
}

protected void Method (object sender, EventArgs e)
{
   //Do work here
}

我需要传递一个参数,所以我想到最简单的方法是这样的:

b.Click += new EventHandler(Method(sender, e, "name"));

protected void Method (object sender, EventArgs e, String name)
{
   //Do work here
}

错误:期望方法名

在查看这里的问题后,我发现几乎每个问题都有相同的解决方案。

b.Click += new EventHandler((sender, e) => Method(sender, e, "name"));

错误: 无法在此作用域中声明名为"sender"的局部变量,因为这会赋予"sender"不同的含义,而它已经在“父级或当前”作用域中用于表示其他内容。

所以我改成了以下内容:

b.Click += new EventHandler((sender1, e1) => Method(sender1, e1, "name"));

在 Visual Studio 中的错误消失了,但是运行网页后,我接收到了这个错误:

System.ArgumentOutOfRangeException:索引超出范围。必须为非负数,并且小于集合大小。

这里出了什么问题,我真的很迷茫。


ArgumentOutOfRangeException 错误是在那个 EventHandler 行抛出的还是其他地方? - keyboardP
也许在ArgumentOutOfRangeException的代码中有一些参考。你应该在这里展示它。 - spender
@keyboardP 是的,就在 EventHandler 那一行。 - Ali Bassam
在ASP的情况下,这个问题有点特殊。您需要在每次回发时重新创建控件,并重新连接事件处理程序。在这样做的过程中,您所关闭的对象在回发之间没有被维护。理想情况下,您应该避免动态添加按钮;这几乎肯定是可能的,也是最理想的选择。 - Servy
2个回答

2

您关于在自定义方法中添加事件处理程序的声明是正确的。错误的来源是其他事物。当您遇到此异常时,请查看 CallStack 并查看实际错误源。


谢谢,问题完全是另外一回事,我感觉太蠢了。 - Ali Bassam

0

如果您订阅了 Button.Click 事件,那么您没有太多选择,因为您的订阅必须遵循相关委托模式。换句话说,您不能将自定义参数添加到事件处理程序中,因为您的处理程序签名必须与您监听的事件上定义的委托类型完全匹配。

因此,要传递参数:

  • 或者定义一个全局状态变量,并从同一事件处理程序中读取它
  • 或者定义一些自定义事件处理程序,带有一些自定义事件参数

我正在尝试保存状态,但找不到适当的变量来存储它。有人说,变量的类型应该是Action,而有些人则说它应该是Func。ShapeNodeEventArgs shapeNodeArgs = new ShapeNodeEventArgs(shapeHit.Tag as DeviceMap);mnuShapeLogicalGrid.Click += (s, ev) => { displayDeviceLogicalData(sender, shapeNodeArgs);};frmDisplay.ContextMenuStrip = ctxtGridStrip;这个问题已经在SO上讨论过了,但我还是无法理解变量类型。欢迎所有评论。 - Sujay Ghosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接