title: WinForms TabControl validation: Switch to a tab where validation failed
body: <p>I currently have a Form with a <code>TabControl</code> containing some <code>TabPage</code>s. Each <code>TabPage</code> has several controls with validation logic and appropriate <code>ErrorProvider</code>s. On my <code>OK_Button_Clicked</code> event, I call <code>Form.ValidateChildren()</code> in order to determine whether to save and close the form . Now, suppose I have a control in tab 1 that fails validation, but the currently visible tab is tab 2. When the user presses OK, he would get no visual indication as to why the form is not closing. I would like to be able to automatically switch to a tab where validation failed, so the user would see the <code>ErrorProvider</code>'s indication of error.</p>
  
  <p>One approach would be subscribing to the <code>Validated</code> and <code>validating</code> events of all appropriate controls, and knowing which tab each of them is in, whenever one fails validation, a list of tabs that failed validation could be built. Since no <code>ValidationFailed</code> event is generated as far as I know, this could be cumbersome (e.g. defining a boolean for each control, setting it to false before validation and to true on its <code>Validated</code> event). And even if I had such an event, I would be forced to listen to many validation events, one for each control that might fail validation, and maintain the list of unvalidated tabs in code. I should note here that subscribing directly to the <code>TabPage</code>'s validation events doesn't work, because they pass as validated even if controls contained inside them fail validation.</p>
  
  <p>Another approach could leverage the fact that the controls in my <code>TabPage</code> happen to be custom controls. I could then make them implement an interface such as:</p>
  
  <pre><code>interface ILastValidationInfoProvider
  {
      public bool LastValidationSuccessful {get; set;}
  }
  </code></pre>
  
  <p>For example:</p>
  
  <pre><code>public MyControl : UserControl, ILastValidationInfoProvider
  {
      MyControl_Validing(object sender, object sender, CancelEventArgs e)
      {
          if (this.PassesValidation())
            this.ErrorProvider.SetError(sender, null);
            LastValidationSuccessful = true;
          else
            e.Cancel = true;
            this.ErrorProvider.SetError("Validation failed!", null);
            LastValidationSuccessful = false;
      }
  }
  </code></pre>
  
  <p>And then, after the call to <code>ValidateChildren</code> I could use code such as:</p>
  
  <pre><code>public void OK_Button_Click
  {
       if (form.ValidateChildren())
           this.Close()
       else
           foreach (TabPage tab in this.TabControl)
               foreach (Control control in tab.Controls)
               {
                   ValidationInfo = control as ILastValidationInfoProvider
                   if (ValidationInfo != null &amp;&amp; !ValidationInfo.LastValidationSuccessful)
                   {
                      this.TabControl.SelectTab(tab);
                      return;
                   }
               }
  }
  </code></pre>
  
  <p>I like this approach better but it doesn't cater to cases where the controls being validated are not custom. </p>
  
  <p>I would gladly use a better approach. Any ideas?</p>
  
  <p><strong>EDIT</strong> I am using <code>Form.AutoValidate = EnableAllowFocusChange</code> (as recommended by Chris Sells in his WinForms book), So the focus can indeed change from controls that failed validation (including moving to other tabs). I have also updated the sample code for the custom control to emphasize the fact that the <code>ErrorProvider</code> resides internally inside it.</p>