为什么我的按钮的'Validating'事件处理程序从未调用过?

Mic*_*l J 2 c# events winforms

在下面的迷你应用程序中,我想知道为什么永远不会调用BtnOk_Validating事件处理程序.我希望单击"确定"按钮可以调用事件处理程序.

真正的对话框有更多控件,每个控件都有一个验证事件处理程序.我的计划是在允许关闭对话框之前使用Ok按钮验证事件处理程序来调用每个其他事件处理程序.

如果不是很明显,那么对于Forms开发来说,我就是新手.

using System.ComponentModel;
using System.Windows.Forms;

namespace ConsoleApp
{
    class Program
    {
        static void Main( string[] args )
        {
            Dialog dialog = new Dialog();

            dialog.ShowDialog();
        }
    }

    public class Dialog : Form
    {
        Button m_BtnOk;
        Button m_BtnCancel;

        public Dialog()
        {
            m_BtnOk = new System.Windows.Forms.Button();
            m_BtnCancel = new System.Windows.Forms.Button();

            m_BtnOk.CausesValidation = true;
            m_BtnOk.DialogResult = DialogResult.OK;
            m_BtnOk.Text = "Ok";
            m_BtnOk.Location = new System.Drawing.Point( 0, 0 );
            m_BtnOk.Size = new System.Drawing.Size( 70, 23 );
            m_BtnOk.Validating += new CancelEventHandler( BtnOk_Validating );

            m_BtnCancel.CausesValidation = false;
            m_BtnCancel.DialogResult = DialogResult.Cancel;
            m_BtnCancel.Text = "Cancel";
            m_BtnCancel.Location = new System.Drawing.Point( 0, 30 );
            m_BtnCancel.Size = new System.Drawing.Size( 70, 23 );

            Controls.Add( this.m_BtnOk );
            Controls.Add( this.m_BtnCancel );
        }

        private void BtnOk_Validating( object sender, CancelEventArgs e )
        {
            System.Diagnostics.Debug.Assert( false ); // we never get here
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:请查看我的后续问题以获得更完整的示例(主要是).

SwD*_*n81 6

这是因为按钮永远不会失焦,因为它是唯一的控件.如果你添加一个TextBox可以占据按钮焦点的东西,那么你会看到它发射.

来自MSDN

通过使用键盘(TAB,SHIFT + TAB等)更改焦点,通过调用Select或SelectNextControl方法,或通过将ContainerControl.ActiveControl属性设置为当前窗体,焦点事件按以下顺序发生:

   Enter    
   GotFocus    
   Leave    
   Validating    
   Validated    
   LostFocus    
Run Code Online (Sandbox Code Playgroud)

使用鼠标或通过调用Focus方法更改焦点时,焦点事件按以下顺序发生:

   Enter    
   GotFocus    
   LostFocus    
   Leave    
   Validating    
   Validated    
Run Code Online (Sandbox Code Playgroud)

如果CausesValidation属性设置为false,则抑制Validating和Validated事件.

更新:与Hans提到的一样,您需要将所有其他控件的每个Validating事件中的验证提取到单独的函数中.然后,您可以创建一个ValidateAll函数来检查所有值.如果函数返回false,那么你不要关闭Form.如果它返回true,你打电话this.Close().所以它可能看起来像这样:

// pseudo code
textbox1.Validating += ValidateTx1();
textbox2.Validating += ValidateTx2();
btnOk.Click += OkBtnClicked();

private void OkBtnClicked(...)
{
    if(ValidateAll())
    {
       this.Close();
    }
}

private bool ValidateTx1(...)
{
   DoTx1Validation();
}

private bool ValidateTx2(...)
{
   DoTx2Validation();
}

private bool ValidateAll()
{
   bool is_valid = DoTx1Validation();
   return (is_valid && DoTx2Validation());
}
Run Code Online (Sandbox Code Playgroud)