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

Nat*_*ing 6 c# winforms

我已经回顾了MSDN文档和几个SO答案,并且所有迹象都表明这有效.在这一点上,我想我完全误解了会发生什么,或者我错过了我需要的一行代码.

简而言之,我有一个带按钮的WinForms应用程序,我想要另一个功能在代码中的某一点"点击"该按钮.这是相关的部分:

// form.Designer.cs

this.btnAddBranch.Click += new System.EventHandler(this.btn_add_Click);
Run Code Online (Sandbox Code Playgroud)

// 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!");
   }
 }
Run Code Online (Sandbox Code Playgroud)

注释行btnAddBranch.PerformClick()是我希望它会相当于它下面的行.但事实并非如此,它在TestClick()调用时似乎没有做任何事情.如果我执行未注释的行,它可以正常工作.

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

Eva*_*n L 10

Your problem is that TestClick() is your form constructor. There are no Controls to call PerformClick() on until the Form Constructor is complete. If you really want to call the code that early then do something like the following.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Calling your PerformClick() anywhere other than the form constructor will create the desired results.


Ala*_*lan 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在浏览时,我注意到的第一个失败是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;
}
Run Code Online (Sandbox Code Playgroud)

在调试器中,您可以在构造函数中放置一个断点,并看到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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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