C# ErrorProvider Want to know if any are Active

20,474

Solution 1

Unfortunately, the ErrorProvider control doesn't provide such functionality. You'd best go with the custom error provider classes from the link you posted.

Otherwise, you could create a method that you would call instead of SetError

int errorCount;
void SetError(Control c, string message)
{
    if (message == "")
        errorCount--;
    else
        errorCount++;
    errorProvider.SetError(c, message);
}

Or you could make an extension method for the ErrorProvider class that would set the error and increment a counter or something along those lines.

And last but not least, you could iterate through all the controls. Slow, but it works:

bool IsValid()
{
    foreach (Control c in errorProvider1.ContainerControl.Controls)
        if (errorProvider1.GetError(c) != "")
            return false;
    return true;
}

Edit

I've written a quick extension class for the error provider:

public static class ErrorProviderExtensions
{
    private static int count;

    public static void SetErrorWithCount(this ErrorProvider ep, Control c, string message)
    {
        if (message == "")
        {
            if (ep.GetError(c) != "")
                count--;
        }
        else
            count++;

        ep.SetError(c, message);
    }

    public static bool HasErrors(this ErrorProvider ep)
    {
        return count != 0;
    }

    public static int GetErrorCount(this ErrorProvider ep)
    {
        return count;
    }
}

I haven't tested it extensively, so you might want to do a bit more validation before calling SetError on your ErrorProvider.

Solution 2

I know this is a bit older question and the extension is working except if someone try to SetErrorWithCount twice for the same object, the count is counted twice. so, here I come with the update extension base on Netfangled extension

public static class ErrorProviderExtensions
{
   private static int count;

   public static void SetErrorWithCount(this ErrorProvider ep, Control c, string message)
   {
       if (message == "")
       {   
          if (ep.GetError(c) != "")
             count--;
       }
       else
          if (ep.GetError(c) == "")
             count++;

       ep.SetError(c, message);
   }

   public static bool HasErrors(this ErrorProvider ep)
   {
       return count != 0;
   }

   public static int GetErrorCount(this ErrorProvider ep)
   {
       return count;
   }
}

Solution 3

OK let me use easier method: currently you are using implicit validation approach... to immediately validate the control.

I think you want to check if all the controls in the form is validated before do some actions, so just check that all the child control is validated. by using The explicit validation approach

in the validating event for each control you can use:-

    Private Sub ProductIDTextBox_Validating(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles ProductIDTextBox.Validating
    If ProductIDTextBox.Text = "" Then
        ErrorProvider1.SetError(ProductIDTextBox, "you have to enter text")
        e.Cancel = True

        Return

    End If
    ErrorProvider1.SetError(ProductIDTextBox, "")

End Sub

then you can check for all the controls by :-

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    If ValidateChildren() Then
        MessageBox.Show("Validation succeeded!")
    Else
        MessageBox.Show("Validation failed.")
    End If
End Sub

hope this will help since i spend hours to find the proper method

Solution 4

It seems like a logical thing to have but unfortunately it's not provided natively.

You could extend the ErrorProvider as other mentioned, or simply iterate all the controls under it and look for an error, something like

bool IsValidationError(ErrorProvider errorProvider, Control.ControlCollection controlCollection)
{
    foreach(Control child in controlCollection)
    {
        // The child or one of its children has an error.
        if (!errorProvider.GetError(child).IsNullOrEmpty() || IsValidationError(errorProvider, child.Controls))
            return true;
    }

    return false;
}

and you'd call IsValidationError(errorProvider, errorProvider.ContainerControl.Controls), or passing a more limited control collection.

Obviously you'd want to avoid iterating tons of controls, but that simple solution should be fine in lots of cases. Also even if you do have tons of controls, you'd probably group them together using Panel, TabControl, GroupBox, ... so you could easily avoid iterating absolutely all the controls.

Note: this is similar to one of the possibilities described in https://stackoverflow.com/a/12327212/276648 except it looks for both null and empty, and it iterates possible grand children recursively.

Share:
20,474
RcK
Author by

RcK

Updated on July 09, 2022

Comments

  • RcK
    RcK almost 2 years

    I want to know if any ErrorProvider are active in my form. being able to find this out might help reduce my code..

    I did find this thing here Counting ErrorProvider

    but incase someone knows a better way... so here goes.

    Ok so basically I have a WinForm which has many TextBoxes Now when user enters values I use Validating to perform validation and if it does not match Regex I set the ErrorProvider ON for that Control.. similarly if the user changes the value to a acceptable one I switch ErrorProvider OFF for that Control..

    but when SAVE is clicked i have to do another check anyways incase the user did not listen to me and change the thing like he was supposed to and still clicked SAVE.. I dont want the thing crashing..

    soo mm is there like a thing where I could say if ErrorProviders is not active then proceed with save else message box saying change it.

    [ANOTHER QUESTION]

    Umm When Validating it only Validates when the Control loses Focus... I kinda of want it to do validation when user stops typing.. I hope you get what I mean

    Like Email Address(textbox) when user is typing his/her name in I [DON'T] want it to do validation yet, but when user has finished entering is waiting for ErrorProvider to disappear(But it doesn't coz it only does that when control loses focus) 2 odd seconds after typing can i make the validation take place?

  • RcK
    RcK over 11 years
    Thanks a lot.. I have not tested it yet... ill do it after my Exam in couple of hours.. but it looks good.. thanks
  • RcK
    RcK over 11 years
    Just tried it.. only just got time.. works thanks.. i chose the extension to do it.
  • Brad
    Brad about 11 years
    Seems like the count++ section should only increment if there is a change. i.e. should be in an if (ep.GetError(c) == "").
  • Emond
    Emond over 10 years
    This won't work with multiple or repeatedly used ErrorProviders because they share the static count field. The code is secretly relying on the fact that the count will be zeroed by the user fixing all the errors!
  • royalTS
    royalTS over 6 years
    I would recommend to use a Dictionary<Control, int> to store the error counts for all controls, by this, it is easy to check whether any control still shows an error.
  • Eric Eskildsen
    Eric Eskildsen over 2 years
    Note: For ValidateChildren() to return false, e.Cancel has to be set to true in a child control's Validating event. That prevents focus from leaving the invalid control by default. For those who would like to disable that behavior, set the form's AutoValidate property to EnableAllowFocusChange.