Control.PerformClick()没有做任何事情,我错过了什么

本文关键字:错过了 什么 任何事 PerformClick Control | 更新日期: 2023-09-27 18:18:42

我已经查看了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()被调用时,它似乎没有做任何事情。如果我执行未注释的行,它可以正常工作。

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

Control.PerformClick()没有做任何事情,我错过了什么

您的问题是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()将创建所需的结果。

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

似乎在构造函数中没有充分创建表单以允许Button.PerformClick()。我推测这可能是由于Modal消息循环尚未完全创建,但在查看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();
    }
}

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

很抱歉最初的答案是错误的。

确保您的表单已经显示:)如果隐藏或未显示,则无法执行单击操作。至少这种方式对我来说是有效的(我显示一个表单一小会儿,执行一个点击,然后立即隐藏它)。

它有效!