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

时间:2013-06-17 19:37:27

标签: c# winforms

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

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

3 个答案:

答案 0 :(得分:9)

您的问题是TestClick()是您的表单构造函数。在Form Constructor完成之前,没有控件可以调用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()将创建所需的结果。

答案 1 :(得分:7)

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

似乎在构造函数中没有充分创建Form以允许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中执行按钮单击。

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

答案 2 :(得分:1)

确保您的表单已显示:) 如果隐藏或未​​显示,则无法执行单击操作。 至少这样它对我有用(我会在短时间内显示一个表格,点击一下,然后立即隐藏它)。

它有效!