TextBox with only numbers
Asked Answered
B

5

6

I need to create a TextBox with only numbers but I couldn't do. I have tried to put : InputScope = "Numbers" but this only work on Mobile. Also I have tried on TextChanging this:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    if (System.Text.RegularExpressions.Regex.IsMatch(textBox1.Text, "[^0-9]"))
    {

        textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1);
    }
}
Bettyannbettye answered 3/10, 2018 at 9:37 Comment(2)
@CodeCaster This is absolutely not a duplicate. The marked question is for WPF technology and the solution does not apply in UWP.Thumbnail
Thanks @CodeCaster , I have posted a full answer.Thumbnail
T
15

You can either prevent any non-numeric input whatsoever, or just filter out digits in the text.

Preventing non-digit input

Use the BeforeTextChanging event:

<TextBox BeforeTextChanging="TextBox_OnBeforeTextChanging" />

And now handle like this:

private void TextBox_OnBeforeTextChanging(TextBox sender,
                                          TextBoxBeforeTextChangingEventArgs args)
{
    args.Cancel = args.NewText.Any(c => !char.IsDigit(c));
}

This LINQ expression will return true and hence Cancel the text change in case it encounters any non-digit character in the input.

Filtering non-digit input

Use the TextChanging event:

<TextBox TextChanging="TextBox_OnTextChanging" /> 

And handle this way:

private void TextBox_OnTextChanging(TextBox sender, TextBoxTextChangingEventArgs args)
{
    //Save the position of the selection, to prevent the cursor to jump to the start
    int pos = sender.SelectionStart;
    sender.Text = new String(sender.Text.Where(char.IsDigit).ToArray());
    sender.SelectionStart = pos;
}

This LINQ query will filter out non-digit characters and create a new string only with the digits in the input.

It is preferable to use TextChanging and BeforeTextChanging, because TextChanged occurs too late, so the user would be confused by seeing characters temporarily display on the screen and immediately disappearing.

Thumbnail answered 3/10, 2018 at 9:51 Comment(3)
Using linq for this is brill.Factoring
Take note, that the BeforeTextChanging event is only available in API contract v5 (Windows v10.0.16299.0) and later. In case you are handling TextChanging instead, you should restore (and adjust) the current selection. Otherwise you'll see the caret jumping around, producing a very poor user experience.Unfreeze
If you bind Text to an int, this solution throws exceptions because an empty string is not automatically converted to 0. If you don't want that, you have to replace "" with "0" in TextChanging.Consign
G
0

Based on the answer https://mcmap.net/q/1645304/-textbox-with-only-numbers for this question.

If you want to also allow input like 100.0 you might have a problem with the decimal point. so

  1. enable the private OnBeforeTextChanging event on the textbox
  2. in the handler:
private void TextBox_OnBeforeTextChanging(TextBox sender,
                                          TextBoxBeforeTextChangingEventArgs args)
{
    double tempDouble;
    args.Cancel  = !(double.TryParse(args.NewText, out tempDouble) | args.NewText == "");

}
Gingras answered 10/3, 2021 at 17:4 Comment(0)
I
0

Building on the accepted answer's solution for filtering out text, if you have to use the TextChanged event:

private void HexTextBox_TextChanged(object sender, EventArgs e)
{
    if (!(sender is TextBox txt))
        return;

    // Filter out any invalid chars that are typed/pasted and leave the cursor where it was (or reasonably close).
    int pos = txt.SelectionStart;
    txt.Text = string.Concat(txt.Text.Where(c => "0123456789abcdefABCDEF".IndexOf(c) != -1));
    txt.SelectionStart = pos;
}

This makes it so someone cannot type unwanted characters into the TextBox. And if they paste them in, they're ignored. E.g. for the above, if you tried to paste in "12#45^" you'd end up with "1245" in the TextBox.

Ignoble answered 22/6, 2021 at 18:16 Comment(0)
C
-1

You can do something else instead of TextBox.Text.Remove function which is Substring function and also you should fix it while they copy a series of characters which includes letters in the centre of the string:-

private void textBox1_TextChanged(object sender, EventArgs e)
{
    var txt = textBox1.Text;

        if (System.Text.RegularExpressions.Regex.IsMatch(txt, "[^0-9]"))
        {
            for (int i = 0; i < txt.Length; i++)
                if (!char.IsDigit(txt[i]))
                    if (i != txt.Length - 1)
                    {
                        //If he pasted a letter inclusive string which includes letters in the middle
                        //Remove the middle character or remove all text and request number as input
                        //I did the second way
                        textBox1.Text = "";
                        break;
                    }
                    else
                    {
                        //If he just typed a letter in the end of the text
                        textBox1.Text = txt.Substring(0, txt.Length - 1);
                        break;
                    }
        }
}
Chromo answered 3/10, 2018 at 11:24 Comment(0)
F
-1

Here is an O(1) solution without string matching

    bool textCanceled = false;

    private void TextBox_KeyDown(object sender, KeyRoutedEventArgs e)
    {
        if (!Char.IsDigit((char)e.Key))
            textCanceled = true;
        else
            textCanceled = false;

    }

    private void TextBox_BeforeTextChanging(TextBox sender, TextBoxBeforeTextChangingEventArgs args)
    {
        args.Cancel = textCanceled;
    }

might have to handle backspace char as a special case

Falmouth answered 11/4, 2019 at 13:59 Comment(1)
A reliable strategy for solving issues is: 1 Make it work. 2 Optionally make it fast. This answer seems to have it backwards: 1 Make it fast. 2 Optionally make it work. This fails to account for a user pasting text using either keyboard or mouse. This proposed answer cannot be fixed to address this.Unfreeze

© 2022 - 2024 — McMap. All rights reserved.