【问题标题】:Can't pass a Button as a parameter不能将按钮作为参数传递
【发布时间】:2014-03-18 16:45:32
【问题描述】:

我在这里尝试做的非常简单,但它对我不起作用。我在 stackoverflow 和其他人上查找了许多非常相似或匹配的问题示例,但他们的解决方案对我不起作用。

基本上(以非常简化的形式),我有一个按钮,里面有一些文字。我想要它,所以当单击此按钮时,会出现一个显示文本的消息框。但是,我有 9 个这样的按钮(想想计算器上的数字),我想创建一个处理所有这些点击的方法,并根据按钮输出正确的文本。这就是为什么我需要将按钮作为参数传递。

这是我目前处理它的方法的代码:

private void btn_Click(object sender, EventArgs e, Button b)
{
    MessageBox.Show(b.Text);
}

上面的小代码sn-p是其他人使用过的相同的解决方案。但是,对我来说,这段代码无法编译并显示一个错误,提示 'btn_Click' 没有重载匹配委托 'System.EventHandler'

当我双击该错误时,它会将我带到表单的 Designer.cs 页面,这是出现错误的代码行:

this.btnN7.Click += new System.EventHandler(this.btnN7_Click);

我不知道重载和委托部分是什么意思,对不起,我对此很陌生。我在想也许重载与构造函数有关,但即使这是正确的,我也不确定下一步会是什么。

我已正确包含 System.Windows.Forms;,因此问题不应该是无法识别 Button 对象。

如果您能提供任何关于我遗漏或做错了什么的见解,那就太好了!如果您需要任何其他信息以继续,请告诉我。

最后,这与我的问题无关,但自从我一周前开始使用 VS 以来,这是一个一直困扰我的小问题:控制参数是 object senderEventArgs e 是为控制器事件自动创建的,甚至是必要的?我在网上查找的大多数示例都省略了它们。我只是保留它们,因为它们是默认创建的,但我真的不知道它们提供什么样的功能,而且我从来没有在我的方法中使用这些参数。

谢谢大家! =)

【问题讨论】:

    标签: c# winforms events


    【解决方案1】:

    您只需要使用sender 参数。如果方法签名与EventHandler 委托不匹配,则无法订阅事件处理程序。

    private void btn_Click(object sender, EventArgs e)
    {
       var currentButton = sender as Button;
       if(currentButton != null) MessageBox.Show(currentButton.Text);
    }
    

    sender 将被分配给触发事件的对象。例如,当您的button2 被点击时,它将被分配给button2。当然您需要将此事件处理程序附加到button2' s 点击事件。我还使用了as 操作符来确保触发一个按钮的事件。以后如果你像btn_Click(this, EventArgs.Empty) 那样手动调用这个方法,那么显式转换 会抛出一个InvalidCastException。使用as 运算符总是更好地避免这种情况。如果sender 的类型与Button 不同,那么currentButton 将是null

    【讨论】:

    • 只是将您的答案与 Ondrej 进行比较,使用 sender 作为 Button 本质上与 (Button) sender 相同;对?在语义上,一种方式比另一种方式更“合适”吗?而且,您检查了按钮是否为空。你能解释一下按钮是如何为空的吗?例如,如果按钮被禁用,按钮是否会为空?谢谢塞尔曼!
    • 这种方式更合适,因为您可以避免像我的情况那样遇到异常。但是如果你确定发送者是一个按钮,你可以按照我的方式去做。
    • @IsaiahLee Selmans 的代码在传递的对象不是按钮的情况下不会执行任何操作(即,如果您将此方法附加为非按钮事件的处理程序,或直接调用它) .另一个答案将引发异常。在这种情况下,我会说很明显抛出异常是可取的。这种特定方法的根深蒂固的假设是发送者是一个按钮。如果不是,那么就有问题了。你希望它对你大喊大叫,而不是把问题扫到地毯下并忽略它,这使得它成为劣等的解决方案。
    • 感谢@Servy 的输入,这对我来说很有意义。我将把 Ondrej 的输入标记为答案,因为它对我手头的具体案例更有意义,但我也确实从 Selman 的输入中学到了东西。这绝对是将来要记住的事情,以防我创建可以被其他对象或控制器访问的方法。谢谢大家!
    • "使用 as 运算符总是最好避免这种情况" 不,不是。事实上,在这个具体的例子中甚至都不是这样,更不用说每个案例了。
    【解决方案2】:

    这就是为什么我需要将按钮作为参数传递。

    您实际上不必创建那个额外的参数。你需要的东西已经在那里了。

    object sender 是事件的来源,所以只需调用

    var btn = (Button) sender;
    MessageBox.Show(btn.Text);
    

    你应该没事的。

    是否需要为控制器事件自动创建的控制参数对象 sender 和 EventArgs e?

    所以现在你对这个问题有了部分答案。第二部分 (EventArgs) 用于传递附加信息。在MSDN 上阅读有关事件参数的更多信息。

    【讨论】:

    • @IsaiahLee 很高兴我能提供帮助。我也会尽力回答您的其他问题。
    • EventArgs 对于单击按钮总是为空,它从不包含任何有意义的信息,因此实际上毫无意义。
    • @Servy 是的,好点。我试图解释它并不总是有用的。
    • 我注意到的一些特殊情况是,即使在这种情况下 EventArgs 始终为空,我也必须将其作为参数包含在内。如果我尝试从参数中删除它并将事件链接到该方法,它只会创建一个包含 EventArgs 的新方法。所以,我想至少对于 VS2010 来说,它是不必要的,但却是必要的。
    【解决方案3】:

    这里有两个选择:

    • 如果您想访问触发事件的按钮,您可以通过sender 进行操作

      private void btn_Click(object sender, EventArgs e)
      {
          Button b = (Button)sender;
          MessageBox.Show(b.Text);
      }
      
    • 否则,直接通过按钮名称访问(以防万一)

    【讨论】:

      猜你喜欢
      • 2022-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-22
      • 2015-02-28
      • 2022-08-03
      • 2018-02-03
      相关资源
      最近更新 更多