如何跳过在单击“取消”button后进行validation

我使用C#。 我有一个Windows窗体与编辑框和取消button。 编辑框在validation事件中有代码。 每次编辑框失去焦点时,代码都会执行。 当我点击“取消”button时,我只想closures窗体。 我不想要执行编辑框的任何validation。 这怎么能做到呢?

这是一个重要的细节:如果validation失败,那么

e.Cancel = true; 

防止离开控制。

但是当用户点击取消button时,表单应该被closures,无论如何。 这怎么能实施?

如果在编辑框失去焦点的时候进行validation,那么取消button就不会停止发生。

但是,如果失败的validation正在阻止取消button的操作,请将该button的CausesValidation属性设置为false

引用: Button.CausesValidation属性

显然,button的CausesValidation属性必须设置为false,然后validation事件不会发生在它的点击。 但是,如果button的父控件的CausesValidation属性设置为true,则可能会失败。 大多数时候,开发人员遗漏/忘记更改容器控件的CausesValidation属性(如面板控件)。 把这也设为False。 这应该是诀窍。

由于某些控件的validation正在阻止它,所以我的表单closures时遇到了问题。 我已经设置了control.CausesValidation = false为取消button和取消button的所有父母。 但仍然有问题。

看起来,如果用户正在编辑正在使用validation的字段,并决定放弃(离开字段的input无效),取消button事件被触发,但窗口不会closures。

在取消button点击事件中,这被修改如下:

 private void btnCancel_Click(object sender, EventArgs e) { // Stop the validation of any controls so the form can close. AutoValidate = AutoValidate.Disable; Close(); } 

将取消button的CausesValidation属性设置为false

CausesValidation属性设置为false

将原因设置为False是关键,但是这仅仅是不够的。 如果父button的CausesValidation设置为true,则validation事件仍将被调用。 在我的一个案例中,我在表单面板上有一个取消button,所以我必须在面板上设置CausesValidation = false和表单。 最后,我用编程的方式做了这件事,因为它比通过所有的forms更简单。

 Control control = cancelButton; while(control != null) { control.CausesValidation = false; control = control.Parent; } 

这些答案都没有完成这项工作,但这个线程的最后一个答案是。 基本上,你需要:

  1. 确保取消button(如果有)具有.CausesValidation设置为false
  2. 覆盖这个虚拟的方法。

     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); } 

我没有真正回答这个问题,只是指出了实际上做过的两个人。

明智地使用Control.CausesValidation属性将帮助你实现你想要的。

为了补充Daniel Schaffer的回答:如果在编辑框失去焦点时发生validation,则可以禁止该button激活绕过本地validation并退出。

 public class UnselectableButton : Button { public UnselectableButton() { this.SetStyle(ControlStyles.Selectable, false); } } 

或者如果你使用DevExpress:

 this.simpleButtonCancel.AllowFocus = false; 

请注意,这样做会改变键盘的使用体验:选项卡将重点放在取消button上。

也许你想使用BackgroundWorker来延迟一点,所以你可以决定是否validation应该运行。 这里是避免窗体closuresvalidation的例子。

  // The flag private bool _isClosing = false; // Action that avoids validation protected override void OnClosing(CancelEventArgs e) { _isClosing = true; base.OnClosing(e); } // Validated event handler private void txtControlToValidate_Validated(object sender, EventArgs e) { _isClosing = false; var worker = new BackgroundWorker(); worker.DoWork += worker_DoWork; worker.RunWorkerAsync(); worker.RunWorkerCompleted += worker_RunWorkerCompleted; } // Do validation on complete so you'll remain on same thread void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (!_isClosing) DoValidationHere(); } // Give a delay, I'm not sure this is necessary cause I tried to remove the Thread.Sleep and it was still working fine. void worker_DoWork(object sender, DoWorkEventArgs e) { Thread.Sleep(100); } 

在编辑框的validation码上方添加:

 if (btnCancel.focused) { return; } 

这应该做到这一点。

在我的情况下,在窗体中我将属性AutoValidate设置为EnableAllowFocusChange

这为我工作。

 private void btnCancelar_MouseMove(object sender, MouseEventArgs e) { foreach (Control item in Form.ActiveForm.Controls) { item.CausesValidation = false; } }