7

我已经查看了 MSDN 文档和几个 SO 答案,所有迹象都表明这是可行的。在这一点上,我想我要么完全误解了会发生什么,要么我错过了我需要的一行代码。

简而言之,我有一个带有按钮的 WinForms 应用程序,我想要另一个函数在代码中的某个位置“单击”该按钮。以下是相关位:

// form.Designer.cs

this.btnAddBranch.Click += new System.EventHandler(this.btn_add_Click);

// form.cs

// using statements
public partial class EditClient : Form
{
   // ...
   public TestClick()
   {
      //btnAddBranch.PerformClick(); <-- would like to know why this fails ...
      btn_add_Click(this, EventArgs.Empty);
   }
   private void btn_add_Click(object sender, EventArgs e)
   {
      MessageBox.Show("You clicked it!");
   }
 }

注释行btnAddBranch.PerformClick()是我希望做的相当于它下面的行。TestClick()但它没有,当被调用时它似乎没有做任何事情。如果我做未注释的行,它工作正常。

我错过了什么,还是我完全误解了什么?

4

3 回答 3

12

你的问题是TestClick()你的表单构造函数。PerformClick()在表单构造函数完成之前,没有可调用的控件。如果您真的想尽早调用代码,请执行以下操作。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        //Do not call methods on controls here, the controls are not yet initialized
    }

    private void TestClick()
    {
        btn_add.PerformClick();
    }

    private void btn_add_Click(object sender, EventArgs e)
    {
        MessageBox.Show("You Clicked it");
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        TestClick();
    }
}

调用PerformClick()表单构造函数以外的任何地方都将创建所需的结果。

于 2013-06-17T19:50:45.597 回答
8

对不起,我已经更新了我的答案以更正它。我最初认为这是因为您没有在 Form.InitializeComponent() 之后调用 Button.PerformClick() (来自 Form.Designer.cs 自动生成的代码),但我更正了这仍然不起作用。

似乎没有在构造函数中充分创建表单以允许 Button.PerformClick()。我推测这可能是因为 Modal 消息循环尚未完全创建,但在查看了 Reflector 中的 Button.PerformClick 代码后,情况似乎并非如此。

PerformClick 的代码如下所示:

public void PerformClick()
{
    if (base.CanSelect)
    {
        bool flag;
        bool flag2 = base.ValidateActiveControl(out flag);
        if (!base.ValidationCancelled && (flag2 || flag))
        {
            base.ResetFlagsandPaint();
            this.OnClick(EventArgs.Empty);
        }
    }
}

在查看时,我注意到的第一个失败是 CanSelect 将返回 false,因为控件当前不可见(尚未调用 ShowDialog)。因此,PerformClick 不会像观察到的那样做任何事情。这是通过深入挖掘 CanSelect 实现:

internal virtual bool CanSelectCore()
{
    if ((this.controlStyle & ControlStyles.Selectable) != ControlStyles.Selectable)
    {
        return false;
    }
    for (Control control = this; control != null; control = control.parent)
    {
        if (!control.Enabled || !control.Visible)
        {
            return false;
        }
    }
    return true;
}

在调试器中,您可以在构造函数中放置一个断点,然后看到 Button1 尚不可见(有意义)。

但是,我建议您可以通过将应用程序逻辑与 Button 的事件处理程序分开来从构造函数中完成您想要的操作。例如...

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        DoSomething();
    }

    private void DoSomething()
    {
        // application logic here... 
        MessageBox.Show("Hello World");
    }

    private void button1_Click(object sender, EventArgs e)
    {
        DoSomething();
    }
}

或者,正如前面的答案所暗示的,您可以从 Form.OnLoad 方法调用 Button.PerformClick() 。但是,最好直接从两个位置调用应用程序逻辑,而不是在 UI 中执行按钮单击。

很抱歉最初的错误答案。希望这有助于解释。

于 2013-06-17T19:53:45.850 回答
2

确保您的表单已显示 :) 如果其隐藏或未显示,则无法执行单击。至少这种方式对我有用(我显示一个表格片刻,执行点击,然后立即隐藏它)。

它有效!

于 2016-03-01T12:14:34.317 回答