C# 使用此.validateChildren()时,如何针对所有无效的表单控件设置errorProvider?

C# 使用此.validateChildren()时,如何针对所有无效的表单控件设置errorProvider?,c#,winforms,validation,errorprovider,C#,Winforms,Validation,Errorprovider,如果我忽略了一些显而易见的事情,我道歉 问题背景 我有一个应用程序,允许用户填写表格,表格的内容将上传到数据库。当他们点击“上传”按钮时,必须验证表单。如果任何字段无效,将向用户发出警报 当前解决方案 当用户点击按钮上载事务时,将调用validFormSelections() if (!this.validateChildren()) { // Display an error return false; } else { return true; } 对于每个组合框

如果我忽略了一些显而易见的事情,我道歉

问题背景

我有一个应用程序,允许用户填写表格,表格的内容将上传到数据库。当他们点击“上传”按钮时,必须验证表单。如果任何字段无效,将向用户发出警报

当前解决方案

当用户点击按钮上载事务时,将调用
validFormSelections()

if (!this.validateChildren())
{
    // Display an error
    return false;
}
else
{
    return true; 
}
对于每个组合框,将调用验证方法,例如

cmbName_Validating(object sender, CancelEventArgs e)
{
    if (/* not valid for whatever reason */)
    {
        errorProvider.Clear();
        e.Cancel = true; 
        errorProvider.setError((Control)sender, /* suitable error message */)
    }
    else
    {
        errorProvider.SetError((Control)sender, ""); 
    }
} 
问题

我想做的是在所有无效的字段旁边显示
errorProvider
,但是现在因为
e.Cancel=true
在单个验证方法中,则(如果我的理解正确的话)在找到第一个无效字段后,它不会继续验证其他字段

我怎样才能调用
this.validateChildren()
并在所有无效字段旁边显示
errorProvider

目前正在尝试研究解决方案

  • 据我所知,我的问题是需要将
    CancelEventArgs
    Cancel
    属性设置为true,因为它“切断”了其余的验证。因此,找到一种方法避免在以后设置此属性,或者找到一种方法解决此问题,这将是一个好主意。但我不知道该怎么做

  • 我最初的想法之一是,如果我能从每个验证事件处理程序返回一个
    布尔值,我就可以相当容易地解决这个问题(然而我怀疑,并且从那时起就知道,我不能这样做)。我发现在事件处理程序中返回值的另一种方法是传入可变值(例如,
    CancelEventArgs
    本身)。这似乎可能是一个合适的解决方案,但我不知道我自己如何才能做到这一点


    • 设置
      e.Cancel=true
      当然是个问题。所以别那么做。这通常是一个相当令人不快的特性,使得数据输入非常模态化。一种更友好的方法是让用户自由地执行数据输入任务,输入数据的顺序不一定是您在设置选项卡顺序时所设想的顺序

      只需编写一个简单的助手方法。例如:

          private Control firstInvalidControl;
      
          private void SetValidation(object sender, bool ok, string errMsg) {
              var ctl = (Control)sender;
              if (ok) errorProvider1.SetError(ctl, "");
              else {
                  if (firstInvalidControl == null) firstInvalidControl = ctl;
                  errorProvider1.SetError(ctl, errMsg);
              }
          }
      
          private void OKButton_Click(object sender, EventArgs e) {
              firstInvalidControl = null;
              this.ValidateChildren();
              if (firstInvalidControl != null) firstInvalidControl.Focus();
              else {
                  // Data is good, use it
                  // ...                
              }
          }
      
      在控件的验证事件处理程序中调用SetValidation()。现在,您可以非常轻松地显示所有适当的警告,并帮助用户导航到可能需要首先处理的控件。例如:

          private Control firstInvalidControl;
      
          private void SetValidation(object sender, bool ok, string errMsg) {
              var ctl = (Control)sender;
              if (ok) errorProvider1.SetError(ctl, "");
              else {
                  if (firstInvalidControl == null) firstInvalidControl = ctl;
                  errorProvider1.SetError(ctl, errMsg);
              }
          }
      
          private void OKButton_Click(object sender, EventArgs e) {
              firstInvalidControl = null;
              this.ValidateChildren();
              if (firstInvalidControl != null) firstInvalidControl.Focus();
              else {
                  // Data is good, use it
                  // ...                
              }
          }
      

      非常感谢你的帮助!很抱歉,我花了这么长时间才接受它,因为我忙于其他项目,没有时间尝试实施它。一个优秀、优雅的解决方案!