为啥我不能将具有用户定义参数的方法分配给 c# 中的按钮?

Posted

技术标签:

【中文标题】为啥我不能将具有用户定义参数的方法分配给 c# 中的按钮?【英文标题】:Why can't I assign a method with user defined parameters to a button in c#?为什么我不能将具有用户定义参数的方法分配给 c# 中的按钮? 【发布时间】:2014-01-08 15:40:29 【问题描述】:

我想将以下方法分配给按钮,以便在单击按钮时运行该方法:

private void settingButton_Click(object sender, EventArgs e , string user , string pass)
    
        frmSetting _settings = new frmSetting(user, pass);
        _settings.Show();   
    

我使用 Visual Studio 2012,并从属性面板中的事件将方法分配给按钮的单击事件。

这里有什么问题?在我添加参数“字符串用户”和“字符串传递”之前,函数 settingButton_Click 在分配给按钮单击事件的方法列表中是可见的,但是一旦我添加这两个参数,我就看不到该方法了在列表中。

编辑:我通过下面的代码传递用户并将参数传递给这个settingButton_Click:

public MainForm(string username, string password)
    
        InitializeComponent();
        settingButton_Click(this, EventArgs.Empty, username, password);
    

【问题讨论】:

这怎么可能行得通?这些参数如何取值? 您需要覆盖点击事件触发器,定义自定义EventArgs 并调用您的新委托事件处理程序。您将无法通过属性面板执行任何操作。这是an example 你为什么要直接调用你的按钮点击事件处理程序?当用户单击按钮时应该调用它。如果需要,您可以将逻辑拆分为另一个函数,并让事件处理程序调用该函数... 您似乎对events 是什么以及它们的工作原理有些误解。 虽然这里的答案试图解释为什么这种方法不起作用,但我认为这里的主要问题是 OP 对整个事件概念缺乏理解。简而言之,他试图在不花时间了解其实施方式的情况下使某项工作发挥作用。 【参考方案1】:

试试这个:

EventHandler eh = (o, args) => settingButton_Click(o, args, username, password);
this.MyButton.Click += eh;

第一个语句创建一个具有正确签名的 EventHandler 实例(即它接受两个参数)。此事件处理程序的实现委托给 settingButton_Click 方法,添加了两个额外的参数。

如果您想覆盖/忽略 'object' 和 'args' 值,以便它们具有 OP 中显示的值,您可以这样做:

EventHandler eh = (o, args) => settingButton_Click(this, EventArgs.Empty, username, password);
this.MyButton.Click += eh;

重点是事件处理程序必须具有正确的签名。传递参数的另一种方法是通过实例字段:

class MainForm : Form

    string username;
    string password;
    public MainForm(string username, string password)
    
        InitializeComponent();
        // set field values
        this.username = username;
        this.password = password;
    

    void settingButton_Click(object o, EventArgs args)
    
        // get field values
        frmSetting _settings = new frmSetting(this.username, this.password);
        _settings.Show();
    

【讨论】:

是的,但是你认为一个控件引发的事件应该以两个独立控件的属性作为参数吗? 这很聪明...但是 args 参数没有按预期使用。重写 EventArgs 类是方法签名的意图。 它很干净,但是使用 lambda 为实际上不是事件的代码创建事件处理程序有什么意义? string username, string password 不是两个独立控件的属性:它们似乎是构造函数参数。另一种方法是将构造函数参数保存为实例字段,以便在事件处理方法中读取它们。 @ChrisW 我使用了您提供的第二个示例,但是语句中用户名的值 this.username = username;为null,而同一语句中的用户名具有我想要的值,怎么可能?【参考方案2】:

点击event需要一定的严格签名,即(object sender, EventArgs e); 所以你不得不这样说(没有其他可用的选项):

  private void settingButton_Click(object sender, EventArgs e) 
    ...
  

但是内部方法没有任何限制,那你为什么不在那里获取用户名和密码

  private void settingButton_Click(object sender, EventArgs e) 
    String user = ...
    String password = ...

    frmSetting _settings = new frmSetting(user, pass);
    _settings.Show();   
  

【讨论】:

【参考方案3】:

你无法做到这一点,因为该方法必须匹配一个特定的签名,类似于这个:

void click_handler(object sender, EventArgs e);

另一种方法是获取用户并通过其他地方:

private void settingButton_Click(object sender, EventArgs e) 
    string user = ... ,
        pass = ... ;

    frmSetting _settings = new frmSetting(user, pass);
    _settings.Show();   

出于好奇,您希望您的代码会发生什么?

编辑

为了反映您的问题编辑,只需创建另一个函数而不是弄乱自定义 EventArgs 等(这样简单的工作 imo 不值得):

private void showSettings(string user, string pass) 
    frmSetting _settings = new frmSetting(user, pass);
    _settings.Show();


private void settingButton_Click(object sender, EventArgs e) 
    string user = ... ,
        pass = ... ;

    showSettings(user, pass);


public MainForm(string username, string password)

    InitializeComponent();
    showSettings(username, password);

【讨论】:

【参考方案4】:

那永远行不通。从按钮事件构造函数中移除字符串传递和字符串用户。

在该页面上为字符串用户和字符串传递创建一个全局变量。在同一类中的其他位置设置这些变量值。然后您可以访问用户的变量并在您的按钮单击事件中传递。

【讨论】:

【参考方案5】:

您要做的是创建一个覆盖 EventArgs 对象的类并将其传入。例如:

public class Credentials : EventArgs 

    public string User  get; set; 
    public string Password  get; set; 


public MainForm(string username, string password)

    InitializeComponent();
    var cred = new Credentials()User = username, Password = password;
    settingButton_Click(this, cred);


private void settingButton_Click(object sender, EventArgs e)

    var cred = (Credentials)e;
    frmSetting _settings = new frmSetting(cred.User, cred.Password);
    _settings.Show();   

【讨论】:

你忘了展示他如何将他的新EventArgs 传递给他的事件处理程序。

以上是关于为啥我不能将具有用户定义参数的方法分配给 c# 中的按钮?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能将从 Firestore 获取的值分配给 Swift 中的数组?

为啥不能将匿名方法分配给 var?

为啥 c# 中的 Random 构造函数在方法末尾分配 Seed 参数?

为啥 C# 可以重载具有相同参数的两个方法,只要其中一个具有默认参数?

为啥可以将切片分配给空接口但不能将其强制转换为相同的空接口

为啥我不能将 new 创建的 &client 对象分配给 unique_ptr