Martel
Martel

Reputation: 2734

Regex does not work to filter TextBox characters in WinForms

I want to create a TextBox (WinForms) that only accepts possitive or negative numbers and any number of character 'k' at the end, I think the pattern is ^-?[0-9]+k*$

I want to prevent the user from writing any character that does not match withe that expression. This is the class that I have implemented:

public class NumTextBox : TextBox {

        private Regex regex;

        public NumTextBox() : base() {
            regex = new Regex(@"^-?[0-9]+k*$");
        }

        protected override void OnKeyPress(KeyPressEventArgs e) {
            String s = Text + e.KeyChar; // current text + new character
            if (!regex.Match(s).Success) {
                e.Handled = true;
            } else {
                e.Handled = false;
            }
            base.OnKeyPress(e);
        }
   }
}

With that, the TextBox does not allow you to write characters at the beginning of the text, but it allows you to write them after some digit, I mean:

asd -> Not allowed

123asd -> allowed, this shouldn't be allowed

I have also tried to add the end character to s but it neither works.

Edit: I have seen in the debugger that the string s has the new character at the end.

Edit 2

Why don't you just TryParse the TextBox's Text value?

Because I want to prevent the user to be able to write not allowed characters, according to the regex.

The code has some other problems too : 1. It should not work if user start to enter a negative number because (-) itself is not matched. 2. what if the text is 123 and user click between 1 and 2 and then press k ?( keypress is not a good place for this)

1: I think you are right, but I prefer to solve this problem now and take care of that later.

2: Letter 'k' shouldn't be allowed between digits, only at the end of the number.

If you debug your code, is the regex matching and stepping into e.Handled=true, or not? Also, OnTextChanged might be a better method to override.

  1. If I debug the code, the regex matchs (says it's correct) wrong strings (f.e. 123asd), so it doesn't step into e.Handled = true.

  2. I think you are referring to override OnTextChanged and delete the last char written if it doesn't match with the regex, don't you? In that case, a problem that I've seen is that the text pointer returns to the beginning.

Upvotes: 2

Views: 849

Answers (2)

Hambone
Hambone

Reputation: 16397

I believe your issue is here:

string s = Text + e.KeyChar; // current text + new character

The problem is that it appends the new character, regardless of the cursor position. This means if you go to the beginning of the string and type in 'k,' then Handled does not fire because you said + 'k', which is fine, per the regex.

It's far from perfect, but you could handle the OnTextChanged in the following way that would meet your needs. I tested it only briefly, but it appears to yield the desired behavior, to the best of my understanding.

protected override void OnTextChanged(EventArgs e)
{
    if (string.IsNullOrEmpty(this.Text))
        return;

    int pos = this.SelectionStart;

    if (!regex.IsMatch(Text))
    {
        this.Text = _OldValue;
        this.SelectionStart = pos > 0 ? pos - 1 : pos;
    }
    else
        _OldValue = this.Text;

    base.OnTextChanged(e);
}

You can see I put in a hack to address the cursor returning to the beginning of the string, which you addressed in your post or comment.

Upvotes: 2

Jhonie
Jhonie

Reputation: 11

What you can do is to check which key is pressed and if its the correct one then you should add it

for your example is this:

int temp;
if(int.TryParse(e.KeyChar,out temp) || e.KeyChar == '-' || e.KeyChar == 'k')
{
//code
}

Upvotes: 0

Related Questions