I\'m thinking about the best way to validate user input.
Let\'s imagine some TextBoxes, CheckBoxes or whatever .NET control you please, where the user input has to
You have some useful facilities in windows forms to perform validation and show error messages including:
Using above options:
IDataErrorInfo Interface
In cases which you have some model classes, the best fit for validation and providing error messages in windows forms is implementing IDataErrorInfo. It's supported by data-binding mechanisms and some windows forms control like DataGridView and ErrorProvider.
To keep things simple you can write validation rules in your class and return error messages using IDataErrorInfo properties. Even if you want to apply a more advanced scenario like using validation engines, at last it's better to implement IDataErrorInfo to gain most consistency with widows forms.
You will use an ErrorProvider to show error messages. It's enough to bind it to your data source and it shows errors automatically.
Validating Event of Controls
In cases that you don't have model classes and all validations should be done against controls, the best option is using Validating event of controls. There you can set e.Cancel = true to set the control state as invalid. Then you can prevent focus change or use the state of control in getting validation summary.
In this case you will use an ErrorProvider to show errors. It's enough to set an error for a control in Validating event this way: errorProvider1.SetError(control1, "Some Error") or you can set an empty error message to remove validation error.
ErrorProvider Component
In both cases when you use databinding or when you use Validating event, as mentioned above, ErrorProvider shows and error icon with a tooltip that shows error message for you near the controls. (DataGridView uses its own mechanism to show errors on rows and cells, without using an ErrorProvider.)
You can also use the component to get a validation summary for your form using GetError method of the component which return the error message of each control.
ValidateChildren Method and AutoValidate Property of Form
You can use ValidateChildren method of form or your container control to check if there is a validation error for your controls or not.
Based on the value of AutoValidate property of your form, it prevents focus change or let the focus change from invalid controls.
All winforms components have a "spare" property which you can use: Tag. It's an object and you can assign whatever to it: it's not used for anything by the framework, and it's useful for cases like this.
If this is going to be generalized, you can just derive your controls and add your properties, but for a one-time single-property, Tag could perfectly work.
// OK
myTextBox.Tag = true;
// NOK
myTextBox.Tag = false;
// Undefined
myTextBox.Tag = null;
To check:
if(myTextBox.Tag is bool)
{
var isOk = (bool)myTextBox.Tag;
if(isOk)
{
// It's OK
} else {
// It's NOK
}
} else {
// It's undefined
}
All that said, I use Tag for simple things and simple logics. If you plan to have more properties or it's a generalized thing... either use the validation mechanisms explained in the other answers, or derive your controls:
public class MyTextBox : System.Windows.Forms.TextBox
{
public bool ValidationOK { get; set; }
}
And change the controls to MyTextBox (if you already have them, open the designer.cs file and change all instances of System.Windows.Forms.TextBox to <yourNamespace>.MyTextBox), etc.
Save the names of your controls to be validated into an array and then just loop through them. You can also set a validation function onto them, if you want to.
var elements = new[] {
new { Control = textBox1 },
new { Control = textBox2 }
};
foreach (var elem in elements)
{
elem.Control.BackColor = string.IsNullOrWhiteSpace(elem.Control.Text) ? Color.Yellow : Color.White;
}
Wrap your Elem array into class objects to add a "ok" property.
It really depends how deep you want to delve into that rabbit hole...
You need to decide on the validation statuses - if it's simply a case of Yes/No, then Boolean/bool will suffice, otherwise you should consider creating an enumeration to hold your validation statuses.
You will need to decide whether you want to extend the controls that require validation, or just use the control's Tag property to store the validation status (personally I think that using Tag to do this is hideous).
An Example:
// Provides your validation statuses.
public enum ControlValidation
{
Ok,
NotOk
}
// Provides a contract whereby your controls implement a validation property, indicating their status.
public interface IValidationControl
{
ControlValidation ValidationStatus { get; private set; }
}
// An example of the interface implementation...
public class TextBox : System.Windows.Forms.TextBox, IValidationControl
{
public ControlValidation ValidationStatus { get; private set; }
...
protected override void OnTextChanged(EventArgs e)
{
ValidationStatus = ControlValidation.Ok;
}
}