C# WinForms验证而不挂起其他控件

C# WinForms验证而不挂起其他控件,c#,.net,winforms,.net-4.5,C#,.net,Winforms,.net 4.5,所以,我在WinForms中遇到了这个问题,至少我认为这是个问题,我不知道如何解决它 基本上,当我为控件实现验证事件处理程序时,当控件验证失败时,我将CancelEventArgs.Cancel设置为true。示例代码: private void NameTextBox_Validating(object sender, CancelEventArgs e) { // Assume Cool Validation Logic. // // ... var isVa

所以,我在WinForms中遇到了这个问题,至少我认为这是个问题,我不知道如何解决它

基本上,当我为控件实现
验证
事件处理程序时,当控件验证失败时,我将
CancelEventArgs.Cancel
设置为true。示例代码:

private void NameTextBox_Validating(object sender, CancelEventArgs e) {
    // Assume Cool Validation Logic.
    //
    // ...
    var isValid = false;
    if (!isValid) {
        e.Cancel = true;

        // Set an Error Provider Message.
        //
        // ...
    }
}
这会导致整个UI挂起。我无法选择任何其他控件、最小化父窗体窗口或退出父窗体窗口。因此,我发现了一个类似的问题,其答案建议为父窗体实现
FormClosing
事件处理程序,并将
FormClosingEventArgs.Cancel
设置为false

问题是,只要我的控件无效,就永远不会调用事件处理程序。我有一种感觉,它可能与我的控制层次有关,尽管我不是100%确定。如果这有帮助的话,那就是:

-- Parent Form

---- Custom User Control

------ Text Box Control (<-- Causes Hang)
——父窗体
----自定义用户控件

------文本框控件(您可以使用async/Wait或BackgroundWorker在UI线程外处理验证:

// in your init code...
textbox.TextChanged+=(s,e)=>Validate();


// and this is the Validation worker
BackgroundWorker validateWorker = null;
bool isValid = false;

private void Validate(){ 
  if (validateWorker != null){
    validateWorker.CancelAsync();
  }
  isValid = false;
  string validateValue = textbox.Text;

  BackgroundWorker localCopy = validateWorker = new BackgroundWorker(); 
  validateWorker.WorkerSupportsCancellation = true;
  validateWorker.DoWork+=(s,e)=>{
    if (CoolValidationAssumed(validateValue) && !localCopy.CancellationPending)
       isValid = true;
  };
  validateWorker.RunWorkerCompleted += (s, e) =>{
     if (!localCopy.CancellationPending && !isValid)
       textbox.Color = Colors.Red;
  }
  validationWorker.RunWorkerAsync();
}

我找到了一个非常简单的解决办法,我真的很沮丧,因为我浪费了我生命中的很多时间,用头敲击键盘

只需将父容器的
ContainerControl.AutoValidate
属性设置为
EnableAllowFocusChange
,即可解决问题。在本上下文中,“父容器”指实际包含输入控件的容器

如果您有控件层次结构,还可以将
ContainerControl.AutoValidate
属性设置为
Inherit
,只需将最外层的容器设置为
enablAllowFocuschange


希望这对将来的人有所帮助。

但这不会使
ValidateChildren()
始终返回true吗?@9ee1您可以在后台线程中验证任何您喜欢的内容,但您必须首先将所有UI数据复制到您的模型中并验证模型(或其临时实例)因此UI控件不可访问我不确定这是否适用于数据绑定
,顺便说一句,它将在UI线程上被调用用于数据绑定,它绝对需要一个
验证的实现来设置
e.Cancel=true;
。否则它将假定您的控件是有效的,并且如果您使用数据绑定,将允许绑定操作。感谢您花时间提供帮助,您将只有一个:)啊。。。我懂了。您可能需要实现自定义验证方案,因为验证需要很长时间。如果可能,您可以在用户在字段中输入数据时在后台线程上预加载一些服务器数据,以加速UI线程验证(idk,如果这是速度慢的原因)