C# ErrorProvider Want to know if any are Active
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.
RcK
Updated on July 09, 2022Comments
-
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 over 11 yearsThanks a lot.. I have not tested it yet... ill do it after my Exam in couple of hours.. but it looks good.. thanks
-
RcK over 11 yearsJust tried it.. only just got time.. works thanks.. i chose the extension to do it.
-
Brad about 11 yearsSeems like the
count++
section should only increment if there is a change. i.e. should be in anif (ep.GetError(c) == "")
. -
Emond over 10 yearsThis 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 over 6 yearsI 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 over 2 yearsNote: For
ValidateChildren()
to returnfalse
,e.Cancel
has to be set totrue
in a child control'sValidating
event. That prevents focus from leaving the invalid control by default. For those who would like to disable that behavior, set the form'sAutoValidate
property toEnableAllowFocusChange
.