Results 1 to 5 of 5

Thread: Validators

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Validators

    Hi,

    I recently got this idea while working in ASP.NET, where one can use Validator controls on a webpage. One simply places the desired Validator next to an input control (TextBox, etc), tells it to validate that control, and when the page posts back (for example, when the user clicks the 'OK' button to submit the page), the Validators check whether their controls passed validation. If they don't, an error is displayed and the postback is canceled.


    I thought it would be useful to have a similar technique in Windows Forms projects, so I made one myself.



    If you have a large 'input form' with a large number of TextBoxes that the user has to enter, then often you would need to validate those TextBoxes (for example, they cannot be empty or they must match a certain pattern). Before the form is submitted, by pressing the OK button, the validation has to pass. This is often done in the OKButton.Click event, where each control in turn is simply checked manually, and the form is only submitted if they all pass.

    To tell the user that validation failed, you could show a MessageBox, or you could use an ErrorProvider. Both of these methods are pretty time consuming and require a lot of boiler-plate code. For example, three textboxes could look like this:
    vb.net Code:
    1. Private Sub OKButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles OKButton.Click
    2.  
    3.     If NameTextBox.Text.Trim() = String.Empty Then
    4.         ErrorProvider1.SetError(NameTextBox, "Name cannot be empty")
    5.         Return
    6.     Else
    7.         ErrorProvider1.SetError(NameTextBox, String.Empty)
    8.     End If
    9.    
    10.     If LocationTextBox.Text.Trim() = String.Empty Then
    11.         ErrorProvider1.SetError(LocationTextBox, "Location cannot be empty")
    12.         Return
    13.     Else
    14.         ErrorProvider1.SetError(LocationTextBox, String.Empty)
    15.     End If
    16.    
    17.     If EmailTextBox.Text.Trim() = String.Empty Then
    18.         ErrorProvider1.SetError(EmailTextBox, "E-mail cannot be empty")
    19.         Return
    20.     Else
    21.         ErrorProvider1.SetError(EmailTextBox, String.Empty)
    22.     End If
    23.    
    24.     'All validation passed
    25.     Me.DialogResult = DialogResult.OK
    26.     Me.Close()
    27. End Sub

    That is a lot of boiler-plate code for just three TextBoxes. It only gets worse if validation means more than just checking if they're empty.




    With these Validator controls, it is a lot easier and a lot quicker. I made a couple of validators, including RequiredFieldValidator (checks for empty fields), RangeValidator (checks if input is within a certain range), RegexValidator (checks if input matches a certain regular expression), but you are free to make your own, I will write a short guide for that at the end.


    What to use them on:
    These validators can be used on any TextBoxBase (that is: TextBox, RichTextBox or MaskedTextBox). I might provide support for other controls at a later stage, but I have not needed it yet.


    How to use:
    So, how do you use them? That's very simple. Just drop the validator you want onto your form. For example, let's assume we have a couple of TextBoxes that cannot be empty. So we need a RequiredFieldValidator.

    The validators are all Components and implement the IExtenderProvider interface to provide properties on the controls to be validated themselves.

    So, once you've dropped a RequiredFieldValidator on your form, you can select the TextBoxes that you want to validate in the designer and look through their properties. They should now have two new properties:
    - ErrorMessage on RequiredFieldValidator1
    - ShouldValidate on RequiredFieldValidator1

    To enable the validator to validate a control, set the ShouldValidate property to True on that control. By default it is false, so keep it on False for controls that do not need to be checked.
    If you wish, you can change the ErrorMessage too, I will come to that later.


    So, once you've enabled validation on the TextBoxes you need, it is time to tell the validator to actually start validating. You should do this right before you 'submit the form', or whatever is supposed to happen in your case.

    For example, I want validation to happen in the OKButton_Click event method, and the form should only be closed if validation passes. To start validation, simply call the Validate function of the validator in question. It returns True if validation was successful for all controls, and False if it failed for one or more controls. So, we only continue if it is True:
    vb.net Code:
    1. Private Sub OKButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OKButton.Click
    2.         If RequiredFieldValidator1.Validate() Then
    3.             Me.DialogResult = Windows.Forms.DialogResult.OK
    4.             Me.Close()
    5.         End If
    6.     End Sub

    That's it!

    The validator will check all the TextBoxes you specified.
    Furthermore, for each TextBox that failed validation, an ErrorProvider is used to show the ErrorMessage:



    Custom handling of validation failure/success:
    If displaying the ErrorProvider icon + tooltip is not what you want when validation failed, then you can cancel it and do something else instead.
    You can do this by handling the ValidationSuccessful and ValidationFailed events of the validator you are using. The event arguments of these events have a property ShowErrorProvider. Set this to False to hide the error provider. Instead of the error provider you can, for example, make the BackColor of the control that was validated Red (on failure) and White (on success):
    vb.net Code:
    1. Private Sub RequiredFieldValidator1_ValidationFailed(ByVal sender As Object, ByVal e As Validators.RequiredFieldValidator.ValidationEventArgs) Handles RequiredFieldValidator1.ValidationFailed
    2.         e.ShowErrorProvider = False
    3.         e.Control.BackColor = Color.Red
    4.     End Sub
    5.  
    6.     Private Sub RequiredFieldValidator1_ValidationSuccessful(ByVal sender As Object, ByVal e As Validators.RequiredFieldValidator.ValidationEventArgs) Handles RequiredFieldValidator1.ValidationSuccessful
    7.         e.ShowErrorProvider = False
    8.         e.Control.BackColor = Color.White
    9.     End Sub



    Other validators

    RangeValidator
    The RangeValidator provides three more extender properties on a TextBoxBase: AcceptEmpty, MinValue and MaxValue. When this validator is used to validate a TextBox, validation is successful only if the text is a valid Integer number, and this integer is between MinValue and MaxValue (both included). If AcceptEmpty is True, an empty TextBox also passes validation. Usage, besides having to set these two properties on each TextBox to validate, is exactly the same.

    The RangeValidator only supports Integer values, but you can always extend it (or create a new validator) to support floating point values as well. I only included this validator to complete the set, as I think using a NumericUpDown control instead is a better candidate.

    RegexValidator
    The RegexValidator provides two more properties on a TextBoxBase: AcceptEmpty and RegexPattern. Validation is successful only if the RegexPattern can match the text in the TextBox. If AcceptEmpty is True, an empty TextBox also passes validation. Can be used to match phone numbers, e-mail addresses, etc. Again, I included it to complete the set, in this case a MaskedTextBox might be a better candidate.

    CustomValidator
    The CustomValidator is a special kind of validator, because it allows you to write the validation code yourself. Instead of doing the validation automatically, this validator raises its Validation event. You should handle the event, and validate the text in the TextBox (obtained via the Control property of the event arguments). If validation fails, you should set the ValidationFailed property of the event arguments to True. For example, suppose the input should be no less than 3 characters long, then you can use this:
    vb.net Code:
    1. Private Sub CustomValidator1_Validation(ByVal sender As System.Object, ByVal e As Validators.CustomValidator.CustomValidationEventArgs) Handles CustomValidator1.Validation
    2.         If e.Control.TextLength < 3 Then
    3.             e.ValidationFailed = True
    4.         Else
    5.             e.ValidationFailed = False
    6.         End If
    7.     End Sub

    You could even validate different controls in a different way by checking which control you are dealing with. A better idea perhaps is to use multiple CustomValidators in that case instead (but make sure to call their Validate methods!).

    Make sure to handle this event, if you don't, validation will succeed by default.



    If you need a different kind of validator, let me know and I can write up a quick guide on how to do that. You can always take a look at how the four validators work, it's not too hard.


    I've attached the five files in a ZIP file. I might cook up an example project later today, but I think the usage should be pretty simple.

    Note that they haven't been tested extensively, but besides one thing, which I'm hoping to solve later today, everything seems to work just fine.

    Known bugs:
    The ValidationSuccessful and ValidationFailed events do not show up in the events list in the designer for some reason. You can still choose them from the dropdowns in the code editor, or just type them manually.



    Files are made in VS2010, so there might be some VS2010 only features. I tried to keep it VS2008 compliant but I might have forgotten something. Just let me know if it doesn't work.

    Enjoy!
    Attached Files Attached Files

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Validators

    I've updated the RangeValidator and RegexValidator components. They now also provide an AcceptEmpty property. If true, empty TextBoxes will pass validation even if they don't match the regular expression or range.

    Furthermore, I've attached a small test solution where the RequiredFieldValidator and RegexValidator are used. VS2010 only, sorry.
    Attached Files Attached Files

  3. #3
    Freelancer akhileshbc's Avatar
    Join Date
    Jun 2008
    Location
    Trivandrum, Kerala, India
    Posts
    7,652

    Re: Validators

    Nice job

    I just did a test run on the second project. And it appears that the "exclamation" icon (used for warning) will blink (in a weird way). Did you do that purposefully as an animation ?

    PS: I didn't looked into the code.


    If my post was helpful to you, then express your gratitude using Rate this Post.
    And if your problem is SOLVED, then please Mark the Thread as RESOLVED (see it in action - video)
    My system: AMD FX 6100, Gigabyte Motherboard, 8 GB Crossair Vengance, Cooler Master 450W Thunder PSU, 1.4 TB HDD, 18.5" TFT(Wide), Antec V1 Cabinet

    Social Group: VBForums - Developers from India


    Skills: PHP, MySQL, jQuery, VB.Net, Photoshop, CodeIgniter, Bootstrap,...

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: Validators

    That is just the default behavior of the ErrorProvider, it blinks when a new error is set. You can access the ErrorProvider via the ErrorProvider property of each Validator in the designer. I'm sure there's a way to disable the blinking, although I never tried it. I do know that you can control the blinking speed (BlinkRate property I think) so surely you can also disable it.

  5. #5
    Freelancer akhileshbc's Avatar
    Join Date
    Jun 2008
    Location
    Trivandrum, Kerala, India
    Posts
    7,652

    Re: Validators

    Thanks...

    I'll check that...

    If my post was helpful to you, then express your gratitude using Rate this Post.
    And if your problem is SOLVED, then please Mark the Thread as RESOLVED (see it in action - video)
    My system: AMD FX 6100, Gigabyte Motherboard, 8 GB Crossair Vengance, Cooler Master 450W Thunder PSU, 1.4 TB HDD, 18.5" TFT(Wide), Antec V1 Cabinet

    Social Group: VBForums - Developers from India


    Skills: PHP, MySQL, jQuery, VB.Net, Photoshop, CodeIgniter, Bootstrap,...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width