Textbox check with Regex expression not allowing d

2019-05-03 22:57发布

问题:

I wanted to make a TextChanged event that would check to see whether the input text fit a particular criteria, and remove the last character entered if it did not. In this case, the criteria is numbers, 1 decimal, and 1 fraction.

I was testing a regex just for numbers and a decimal and ran into an issue. I've tried several different expressions (I'm terrible at writing my own, so they are picked up from various other stack overflow questions), and the result is the same every time. It accepts numbers just fine, but it doesn't accept decimals. Any help would be greatly appreciated!

        string isNumber = @"^\d{1,9}(\.\d{1,9})?$";

        private void TextBox_TextChanged(object sender, EventArgs e)
        {
            TextBox text = (TextBox)sender;

            Match match = Regex.Match(text.Text, isNumber);

            if (!match.Success)
            {
                if (text.Text.Length > 1)
                    text.Text = text.Text.Substring(0, text.Text.Length - 1);
                else
                    text.Text = "";

                text.Select(text.Text.Length, 0); //set cursor to the end 
                                                  //of the string
            }
        }

回答1:

I think the problem is that you are trying to validate the number character-by-character as the user types, but it is not possible to type a valid decimal number without the value being an invalid value temporarily.

Consider what happens as the user types the value 1.2:

  1. The user types the character 1.
  2. Validation fires because the value of the textbox changed.
  3. 1 is a valid decimal, so validation passes.
  4. The user continues typing, adding the decimal point character .
  5. Validation fires again because the value of the textbox changed.
  6. 1. is not a valid decimal according to the regular expression, so the last character is erased.
  7. The value of the text box is now back to 1.
  8. The user gets frustrated. Goto step 4.

As you can see, it's not possible to enter the decimal point. But, if you try to change your regular expression to allow a decimal point to exist without a following digit, then you could have an invalid value if the user stops after typing the decimal point and then submits the form.

So the point is, using a character-by-character validation scheme will not work for decimals. A better approach would be to allow the user to enter whatever they want in the box and then validate later when the user is finished typing. You can do this by validating when the textbox loses focus or when the form is submitted.



回答2:

This isn't the prettiest, but it seems to do what you need:

^(\d{1,9}\.|)\d{1,9}(\.(\d{1,9})?)$

I should note that this will not work for a number starting with a decimal.



回答3:

One problem at least is with what(and how) you are trying to do(like brian pointed out so good),you probably mean something that only allows the first 3 characters of textbox to be the format "1.3" for example and removing the char if its not the correct one at that position. If you really intended to do that you can do this(i did not place any code for the case if the user after success places another character,in this case the fourth char):

        string isNumber = @"^[1-9]{1}\.[1-9]{1}$";
        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            TextBox text = (TextBox)sender;

            Match match;

            switch (text.Text.Length)
            {
                case 1:
                    if (char.IsDigit(text.Text[0]))
                        break;
                    else
                        text.Text = "";
                    break;
                case 2:
                    if (char.IsPunctuation(text.Text[1]))
                        break;
                    else
                    {
                        text.Text = text.Text.Remove(text.Text.Length - 1, 1);
                        text.Select(text.Text.Length, 0); 
                    }
                    break;
                case 3:
                    match = Regex.Match(text.Text, isNumber);
                    if (!match.Success)
                    {
                        text.Text = text.Text.Remove(text.Text.Length - 1);
                        text.Select(text.Text.Length, 0); 
                    }
                    else
                        MessageBox.Show("Success!!!!!");
                    break;
            }

        }

As you see i do char by char check until it reaches 3 in lenght,then i check for the regex.