WinForms验证没有挂其他控件

问题描述:

所以,我在WinForms中遇到了这个问题,至少我认为它是一个问题,我无法弄清楚如何解决它。WinForms验证没有挂其他控件

基本上,当我为某个控件实现Validating事件处理程序时,我在控件未通过验证时将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) 

任何想法将不胜感激。

我发现了一个解决方案,它是如此简单,事实上,我不高兴我浪费了我的生活如此多小时翻动我的头靠在键盘上。

只需将父容器的ContainerControl.AutoValidate属性设置为EnableAllowFocusChange并解决问题即可。本文中的“父容器”表示实际容纳输入控件的容器。

如果您拥有控制层次结构,则还可以将ContainerControl.AutoValidate属性设置为Inherit,并将最外层容器设置为EnableAllowFocusChange

希望这可以帮助未来的人。

您可以使用异步/坐等或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(); 
} 
+0

但不会使'ValidateChildren()'总是返回true吗? – 9ee1 2013-04-23 21:09:44

+0

@ 9ee1你可以在后台线程中验证你喜欢的任何东西,但是你必须首先将所有UI数据复制到模型中,然后验证模型(或其临时实例),以便不访问UI控件 – 2013-04-24 01:02:07

+0

I我不确定这是否会与数据绑定一起工作。另外,如果你查看'ValidateChildren()'的源代码,顺便在UI线程中调用数据绑定的方法,那么绝对需要实现'Validating'来设置'e.Cancel = true;' 。否则,它会假定你的控件是有效的,如果你使用数据绑定,将允许绑定操作。谢谢你花时间帮忙,你是唯一一个:) – 9ee1 2013-04-24 22:56:21