4

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 be validated as OK or NOK. As soon as the user's filled up all required fields he submits via a button.

Now I have to know which fields were previously confirmed as OK and which as NOK. By now I've always handled such cases by declaring a global bool variable for every control to tell me so. But I don't like that...

I'm pretty sure there must be another way! What I would like to do is expanding these .NET controls with a OK or NOK property called status or similar. Can you do that? And if so how do you do it? Is something like that already existing?

Thank you for your response!

leppie
  • 115,091
  • 17
  • 196
  • 297
Mr. Toast
  • 941
  • 3
  • 11
  • 27

4 Answers4

5

You have some useful features in windows forms to perform validation and show error messages including:

Using above options:

  • You can perform validation when you are using data-binding to model classes.
  • You van perform validation when you don't use data-binding.
  • You can show error messages and an error icon near the controls which are in invalid states.
  • You can decide to prevent the focus change from invalid controls or let the focus change.
  • You can show a validation summary for your form.
  • You can also apply DataAnnotations Validations in Windows Forms

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.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
0

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.

Yannick Meeus
  • 5,643
  • 1
  • 35
  • 34
Thomas
  • 213
  • 2
  • 9
0

It really depends how deep you want to delve into that rabbit hole...

  1. 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.

  2. 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;
    }
}
Matthew Layton
  • 39,871
  • 52
  • 185
  • 313
0

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.

Jcl
  • 27,696
  • 5
  • 61
  • 92