当子窗体关闭时,为什么不对主窗体中创建的窗体上的控件触发Validated事件?

ror*_*.ap 5 .net c# events winforms

假设我有一个winforms应用程序,有两个表单,即程序运行时启动的主表单,以及另一个表单.以下是主窗体的代码:

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

    private void button1_Click(object sender, EventArgs e)
    {
        var f2 = new Form2();
        f2.ShowDialog();
    }

    private void textBox1_Validated(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.Print("Main Form: Validated!"); 
    }
}
Run Code Online (Sandbox Code Playgroud)

这是儿童形式:

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void textBox1_Validated(object sender, EventArgs e)
    {
        System.Diagnostics.Debug.Print("Child Form: Validated!");  
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行应用程序时,我可以将焦点放在主窗体上的文本框中,当然,当我标签出来时,它会触发Validated事件并打印Main Form: Validated!到输出. 如果我将焦点放在文本框中并关闭主窗体(即结束程序),也会发生这种情况.

当我单击主窗体上弹出子窗体实例的按钮时,我可以将焦点放在子窗体的文本框中,并且Validated当我跳出它时,事件将触发.但是,与关闭表单时的主要表单行为不同,如果我将焦点放在子表单上的文本框中并关闭子表单,Validated事件永远不会触发.

为什么验证事件不会触发,有没有办法可以解雇它.

我依靠某些控件的验证事件来更新我的视图模型.我想确保即使丢失焦点是由于表格关闭甚至应用程序本身结束,它们也总是会触发.

Han*_*ant 10

这是由ShowDialog()引起的.这是一个记录在案的错误,.NET 1.x中的一个错误,它们无法再修复.从Form.cs 源代码:

   // NOTE: We should also check !Validate(true) below too in the modal case,
   // but we cannot, because we didn't to this in Everett (bug), and doing so
   // now would introduce a breaking change. User can always validate in the
   // FormClosing event if they really need to. :-(
Run Code Online (Sandbox Code Playgroud)

所以只需按照指导:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        if (e.CloseReason == CloseReason.UserClosing && this.DialogResult != DialogResult.Cancel) {
            if (!base.Validate(true)) e.Cancel = true;
        }
        base.OnFormClosing(e);
    }
Run Code Online (Sandbox Code Playgroud)

假设您在解除对话框时不需要该事件,并且您希望在验证失败时对话框保持打开状态.后一个条款是新行为.


Pav*_*aka 1

如果您愿意,所有模式对话框控件都会在关闭时进行验证。您可能可以采用以下方法...这肯定会触发文本框验证事件。

在 Form2 中添加表单关闭事件并调用ValidateChildren()

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
    this.ValidateChildren();
}
Run Code Online (Sandbox Code Playgroud)