Click here to Skip to main content
15,041,525 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I am trying to validate a textbox in windows form to accept user input in certain format
I need user input as first 3 digits as number 405 & 505 followed by year ranging 1950-current year, followed by six digit unique identifier.

I need to validate textbox with leave event, such that it verifies user input matches the format on tab button click, mouse click to other field.

Textbox is 13 digit.

private void txtsfn_Leave(object sender,EventArgs e)
{
// need help with this part
}

Any suggestions and help is appreciated.
Posted
Updated 6-Nov-15 8:19am
v2
Comments
ZurdoDev 6-Nov-15 14:40pm
   
You could easily parse the string and check to make sure it matches, or you can use RegEx. There are online tools to help you build a regex statement.
Member 12076824 6-Nov-15 15:04pm
   
Thanks for response, I am not expert with regex and had been trying to avoid using regex. It gets somewhat complicated in my case.
ZurdoDev 6-Nov-15 15:08pm
   
In that case use SubString() to make sure each section is what you expect.
BillWoodruff 6-Nov-15 14:54pm
   
Read the documentation on the Masked TextBox.
ZurdoDev 6-Nov-15 15:09pm
   
Masking won't actually give the OP what they need. For example, it won't ensure a year is entered in digits 4-7.
BillWoodruff 6-Nov-15 16:39pm
   
Hi RyanDev, no, masking won't give the user everything they want in one go, but it can enforce basic constraints.

If you want to use a MaskedTextBox:
C#
// the character here should be whatever you set
// as the PromptChar property of the MaskedTextBox
private char[] splitchar = new char[1] {'-'};
private string[] fields;

private void resetMTB()
{
    // for debugging only
    Console.WriteLine("bad input: ", maskedTextBox1.Text);

    maskedTextBox1.Clear();
    maskedTextBox1.Focus();
    maskedTextBox1.Capture = true;
}

private void maskedTextBox1_Leave(object sender, EventArgs e)
{
    if(maskedTextBox1.Text.Length != 15)
    {
        resetMTB();
        return;
    }

    fields = maskedTextBox1.Text.Split(splitchar);

    int field1;

    if (fields.Length == 3)
    {
        if (fields[0].Length == 3
            && fields[1].Length == 4
            && fields[2].Length == 6)
        {
            if (Int32.TryParse(fields[1], out field1))
            {
                if (field1 >= 1950 && field1 <= DateTime.Now.Year) return;
            }
        }
    }

    resetMTB();
}
Note: this code was written quickly, and tested with only a small range of inputs; be sure and test thoroughly before you use this in "production" code.
   
Comments
George Jonsson 6-Nov-15 18:34pm
   
The length of the string is supposed to be 13.
BillWoodruff 6-Nov-15 19:57pm
   
Hi George, when you use a MaskedTextBox, the Prompt Character is inserted between fields: in this case there are two places where the Prompt is inserted resulting in a string length of #15 when you read out the Text in the MaskedTextBox. Checking for length == #15 first eliminates the case where the user has not filled in every field with the expected number of characters.
George Jonsson 6-Nov-15 20:00pm
   
Ah OK. I have to admit I have only used that component once or twice.
One learn something new every day.
Thanks Bill.
Member 12076824 7-Nov-15 14:04pm
   
Thanks Geoge, I tested this worked fine.
This is pretty easy to do with a regular expression.
To learn about that you can use this site as a starting point: Regular Expression Info[^]

And why not use the Validating event[^] for the text box? It is kind of made for this purpose. And it will trigger when the focus leaves the control.

Make sure to add
C#
using System.Text.RegularExpressions;

also add this as a member of your class
C#
private static Regex exprNumber = new Regex("^(405|505)(19[5-9][0-9]|[2-9][0-9]{3})[0-9]{6}$");

* The ^ anchor will make sure that you start the evaluation at the start of the string
* (405|505) means either 405 or 505
* 19[5-9][0-9] means 19 followed by a digit >=5 followed by 1 digit in the range of 0-9.
* 2[0-9]{3} means 2 - 9 followed by 3 digits in the range of 0-9. 2000 - 9999
* (19[5-9][0-9]|2[0-9]{3}) means either a number between 1950-1999 or between 2000-9999
* [0-9]{6} means exactly 6 digits in the range 0-9
* The $ anchor means that no extra characters can be matched.
* The total number of allowed characters is 13
Note: [0-9] can be replaced by \d, which is shorter but can be more difficult to read

In the event you can do something like this
C#
private void txtsfn_Validating(object sender, CancelEventArgs e)
{
    if (!exprNumber.IsMatch(txtsfn.Text))
    {
        // Show an error message or something
        e.Cancel = true;    // Prevents the user from leaving the form
        txtsfn.Focus();     // Set focus to the control that should be edited
    }
}


[UPDATE]
I don't know a way to check for current year in pure regular expression, but you can do it with some extra coding.
(Maybe there is a way to do it in regex only, but in that case you better ask separate question)

First change the expression a bit
C#
private static Regex exprNumber = new Regex("^(405|505)(?<year>19[5-9][0-9]|[2-9][0-9]{3})[0-9]{6}$");

(?<year>19...) represents a named group that makes it easy to extract the year part later

Then change your validation code a little:
C#
private void txtsfn_Validating(object sender, CancelEventArgs e)
{
    Match m = exprNumber.Match(txtsfn.Text);
    int testedYear = 0;

    // m.Groups["year"].Value will contain the year upon success
    // and be empty if the match fails
    int.TryParse(m.Groups["year"].Value, out testedYear);

    int currentYear = DateTime.Now.Year;
    
    if (!m.Success || testedYear > currentYear)    
    {
        // Show an error message or something
        e.Cancel = true;    // Prevents the user from leaving the form
        txtsfn.Focus();     // Set focus to the control that should be edited
    }
}
   
v4
Comments
Member 12076824 6-Nov-15 20:11pm
   
Thanks for response I will try this.
Member 12076824 9-Nov-15 17:06pm
   
Hi George,

Thanks for all your help. I was wondering is there way to restrict year to current year in regular expression and need not make changes to code for next year?
George Jonsson 9-Nov-15 20:39pm
   
I don't know a way to do it in pure regular expression, but I updated my solution with some extra code that takes care of that problem.
Member 12076824 10-Nov-15 11:26am
   
Thanks for all your help.
George Jonsson 10-Nov-15 17:34pm
   
Your welcome.
Member 12076824 10-Nov-15 18:40pm
   
Hi Goerge,

I need help with this regex expression.

I am trying to use below expression.

("^(4|5)(?<year>19[5-9][0-9]|[2-9][0-9]{3})(0[1-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9]|6[0-3]{2})[0-9]{6}$");

where textbox input starts with 4/5 followed by 4 digits for year and next 2 digits code 01 - 63. It works fine till 59 but gives error from 60 -63. Can you please have a look?

Thanks.
George Jonsson 10-Nov-15 19:38pm
   
I will have a look, but post it as a new question.
You even have a specific forum for regular expressions:
http://www.codeproject.com/Forums/1580841/Regular-Expressions.aspx[^]
George Jonsson 10-Nov-15 20:23pm
   
This regex takes are of 01-63:
(0[1-9]|[1-5][0-9]|6[0-3])
01-09 10 - 59 60 - 63
Member 12076824 10-Nov-15 22:12pm
   
Thank Goerge, I appreciate all your help.
Member 12076824 16-Nov-15 18:12pm
   
Hi Goerge,

Sorry to bother you again.

I am trying to use same technique on click of a button, but I am facing issues with year greater than current year, Can you please have a look, if I missed something?

private static Regex exprNumber = new Regex(^(405|505)(?19[5-9][0-9]|[2-9][0-9]{3})[0-9]{6}$");

if (txtsfn.Text != "" && txtlrn.Text !="" && txtovrbn.Text != '' && txtovrts.Text != "" && txtfpfn.Text != "" && txtfpln.Text != "" && txtfpfn.Text.Length >= 2 && txtfpln.Text.Length >= 2 &&txtsfn.Text.Length == 13 && txtlrn.Text.Length == 13)
{
// m.Groups[year].Value will contain the year upon success
// and be empty if the match fails
Match m = exprNumber.Match(txtsfn.Text);
int testedYear = 0;
int.TryParse(m.Groups[year].Value, out testedYear);
int currentYear = DateTime.Now.Year;

if (!m.Success || testedYear > currentYear)
{

txtsfn.Focus(); // Set focus to the control that should be
}
}

Thanks.
George Jonsson 16-Nov-15 18:30pm
   
Time to ask a new question.
Member 12076824 16-Nov-15 22:48pm
   
I am sorry George, I asked question, but some one pointed out I am asking same question again, so I deleted that.

I added question, please have a look.
http://www.codeproject.com/Questions/1056517/Regex-expression-to-validate-textbox
BillWoodruff 7-Nov-15 3:14am
   
+5
George Jonsson 7-Nov-15 3:24am
   
Thanks Bill.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)




CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900