I realize this thread is pretty old but I thought I'd post the solution I came up with. Basically when the form is submitted, a routine will check the controls and determine if validation is defined on each control. If it is, the validating method is executed on each one and if any of them fail, the routine returns a failure allowing the process to stop. This solution works well especially if you have several forms to validate.
1) Add this code to your project. We're using Reflection so you need to add System.Refelection to your using statements
class Validation
{
public static bool hasValidationErrors(System.Windows.Forms.Control.ControlCollection controls)
{
bool hasError = false;
// Now we need to loop through the controls and deterime if any of them have errors
foreach (Control control in controls)
{
// check the control and see what it returns
bool validControl = IsValid(control);
// If it's not valid then set the flag and keep going. We want to get through all
// the validators so they will display on the screen if errorProviders were used.
if (!validControl)
hasError = true;
// If its a container control then it may have children that need to be checked
if (control.HasChildren)
{
if (hasValidationErrors(control.Controls))
hasError = true;
}
}
return hasError;
}
private static bool IsValid(object eventSource)
{
string name = "EventValidating";
Type targetType = eventSource.GetType();
do
{
FieldInfo[] fields = targetType.GetFields(
BindingFlags.Static |
BindingFlags.Instance |
BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
if (field.Name == name)
{
EventHandlerList eventHandlers = ((EventHandlerList)(eventSource.GetType().GetProperty("Events",
(BindingFlags.FlattenHierarchy |
(BindingFlags.NonPublic | BindingFlags.Instance))).GetValue(eventSource, null)));
Delegate d = eventHandlers[field.GetValue(eventSource)];
if ((!(d == null)))
{
Delegate[] subscribers = d.GetInvocationList();
// ok we found the validation event, let's get the event method and call it
foreach (Delegate d1 in subscribers)
{
// create the parameters
object sender = eventSource;
CancelEventArgs eventArgs = new CancelEventArgs();
eventArgs.Cancel = false;
object[] parameters = new object[2];
parameters[0] = sender;
parameters[1] = eventArgs;
// call the method
d1.DynamicInvoke(parameters);
// if the validation failed we need to return that failure
if (eventArgs.Cancel)
return false;
else
return true;
}
}
}
}
targetType = targetType.BaseType;
} while (targetType != null);
return true;
}
}
2) Use the Validating event on any control you want to validate. Be Sure to use e.Cancel when the validation fails!
private void txtLastName_Validating(object sender, CancelEventArgs e)
{
if (txtLastName.Text.Trim() == String.Empty)
{
errorProvider1.SetError(txtLastName, "Last Name is Required");
e.Cancel = true;
}
else
errorProvider1.SetError(txtLastName, "");
}
3) Don't skip this step! Set the AutoValidate property on the form to EnableAllowFocusChange. This will allow tabbing to another control even when the validation fails.
4) Finally call the form validation on the button click
private void btnSubmit_Click(object sender, EventArgs e)
{
// the controls collection can be the whole form or just a panel or group
if (Validation.hasValidationErrors(frmMain.Controls))
return;
// if we get here the validation passed
this.close();
}
Happy Coding!