WinForms验证事件阻止Escape键关闭表单

Dav*_* R. 13 .net c# validation winforms

我有一个带有单个TextBox的简单表单,以及OK和Cancel按钮.Form的AcceptButton和CancelButton设置正确,OK和Cancel按钮的DialogResult设置为'OK'和'Cancel'.

我想在TextBox中添加验证,这将阻止用户在验证失败时对表单进行确认,但这也将允许它们像往常一样取消.

默认情况下,在所有控件上,CausesValidation属性为True,但我在取消按钮上将其更改为False.

果然,单击"确定"或按Enter键将运行我连接到TextBox的验证事件.按取消按钮绕过验证,这是完美的.

然而,按Escape取消形式并没有执行一样按下取消按钮-它引发Validating事件,并防止使用者从离开.

是否有任何方法可以使Escape键按预期执行,即不提高Validating事件,就像按下取消按钮一样?

一个完整的解决方案是:

创建一个新的Windows窗体应用程序.将第二个表单添加到项目中.

在InitializeComponent()之后将此代码粘贴到Form1的构造函数中:

MessageBox.Show((new Form2()).ShowDialog().ToString());
Run Code Online (Sandbox Code Playgroud)

这显示了从我们的第二个表单传回的DialogResult.

在InitializeComponent()之后将此代码粘贴到Form2的构造函数中:

TextBox txtName = new TextBox();

txtName.Validating +=
    new CancelEventHandler((sender, e) =>
    {
        if (txtName.Text.Length == 3)
        {
            MessageBox.Show("Validation failed.");
            e.Cancel = true;
        }
    });

Button btnOk = new Button
{
    Text = "OK",
    DialogResult = DialogResult.OK
};
Button btnCancel = new Button
{
    Text = "Cancel",
    CausesValidation = false,
    DialogResult = DialogResult.Cancel
};
FlowLayoutPanel panel = new FlowLayoutPanel();
panel.Controls.AddRange(new Control[] 
{
    txtName, btnOk, btnCancel 
});

this.AcceptButton = btnOk;
this.CancelButton = btnCancel;

this.Controls.Add(panel);
Run Code Online (Sandbox Code Playgroud)

在这个简化的示例中,如果输入了3个字符,则文本框将不允许您继续.即使有3个字符,您也可以直接按取消按钮或关闭表格; 但是按下Escape键会这样做 - 它会触发Validating事件,而它应该与按Cancel取消相同.

Han*_*ant 16

是的,这是ValidateChildren方法的一个尴尬的怪癖.它不知道取消是有意的.粘贴此代码以解决问题:

    protected override void OnFormClosing(FormClosingEventArgs e) {
        base.OnFormClosing(e);
        e.Cancel = false;
    }
Run Code Online (Sandbox Code Playgroud)

要避免运行导致副作用的Validate事件处理程序(如消息框),请将此语句添加到方法的顶部:

    private void txtName_Validating(object sender, CancelEventArgs e)
    {
        if (this.DialogResult != DialogResult.None) return;
        // etc..
    }
Run Code Online (Sandbox Code Playgroud)

将此代码粘贴到表单中以在尝试验证表单之前设置DialogResult:

    protected override bool ProcessDialogKey(Keys keyData) {
        if (keyData == Keys.Escape) this.DialogResult = DialogResult.Cancel;
        return base.ProcessDialogKey(keyData);
    }
Run Code Online (Sandbox Code Playgroud)


gal*_*mok 6

我刚看到这个问题,因为我正在寻找相同的解决方案,并且ProcessdialogKey的覆盖是MS批准的解决方案,直到他们修复了错误(Escape应该像单击取消一样).此处也可以找到对此错误的讨论(仅使用Visual Basic而不是C#.错误已超过5年,显然仍未修复):错误还是功能?CancelButton vs Escape Key我正在尝试解决C++解决方案.

编辑添加:来自C#链接的解决方案:

protected override bool ProcessDialogKey(Keys keyData)
{
    if (keyData == Keys.Escape)
    {
        this.AutoValidate = AutoValidate.Disable;
        cancelButton.PerformClick();
        this.AutoValidate = AutoValidate.Inherit;
        return true;
    }
    return base.ProcessDialogKey(keyData);
}
Run Code Online (Sandbox Code Playgroud)