Ian W
Ian W

Reputation: 411

Validating user input of decimal number

I have a wpf text box and I want to check as the user inputs into it that they are only using 0 1 2 3 4 5 6 7 8 9 . [Decimal Point] characters for decimal numbers. I use this textbox to convert to a decimal later

I am using the follow articles as a starting point Regex Match Preview Text Input example regex-to-allow-one-decimal-number-or-a-range-of-decimal-number

Here is my xaml

<TextBox Grid.Column="1" Height="28" HorizontalAlignment="Left" Margin="10,10,0,0" Name="tbTaxFreeLimit" Width="90" VerticalAlignment="Top" 
                                             AcceptsTab="True" 
                                             PreviewTextInput="tbDecimalCheck_PreviewTextInput"
                                            />

And c#

private void tbDecimalCheck_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
     // Test for decimal
     if (IsNumeric(e.Text)==false)
         e.Handled = true;
}

private bool IsNumeric(string s)
{
    Regex r = new Regex(@"^[0-9]");

    return r.IsMatch(s);
}

This example works fine for 0 1 2 3 4 5 6 7 8 9 but I can not enter the decimal point .

If I change the to following code below it has no effect

Regex r = new Regex(@"^[0-9].");

Upvotes: 0

Views: 17304

Answers (4)

user2662006
user2662006

Reputation: 2294

System.Text.RegularExpressions.Regex.IsMatch(txtTransactionAmount.Text, @"[^0-9].[^0-9]")

Upvotes: 0

R Day
R Day

Reputation: 972

A regular expression may not be the most readable/maintainable way to do this.

Try parsing it;

private bool IsNumeric(string s) => decimal.TryParse(s, out var value);

Upvotes: 3

Matt Burland
Matt Burland

Reputation: 45135

Your regex ^[0-9]. is saying from the start of the string match one character in the range 0-9 and then match any character (. means any character). That's not what you want. You'd need to match any number of characters, an optional decimal point, and then a bunch more numbers. Something like:

^\d+\.?\d*$

Which says 1 or more (+) digit (\d is equivalent to [0-9]), 0 or 1 (?) decimal point (the . has to be escaped to match a literal . hence \.) and then 0 or more (*) digits.

This fixes your regex, but doing this on a text input is kind of a pain and you are better off letting the user enter text and then validating it with something like decimal.TryParse rather than trying to restrict while they type. Why? Consider the user enters:

1     // this is valid

And then:

1.    // this is still valid

And then:

1.2   // still valid

And then they realize they meant 2.2, so what do they do? They delete the 1 to give:

.2     // Buzzzz, not valid

That's really annoying for a user. The user tries to delete the 1 and the control stubbornly keeps rejecting the change. Why? The user doesn't know. Don't turn entering user input into a game of "guess what the rules are".

Another thing to consider, which may or may not be a problem for you, is that not all cultures use . as a decimal separator. In fact most of the world doesn't.

So don't cancel text entry, use TryParse (with appropriate cultural settings) and just set an error on the TextBox rather than stop user entering text. Just don't let the user go to whatever the next stage is until they resolve the problem with the numeric entry.

Upvotes: 5

dgavian
dgavian

Reputation: 250

Something like:

Regex r = new Regex(@"^\d+\.?\d*$");

Explanation: "^" matches the beginning of the string; \d+ matches one or more digits, \.? matches an optional decimal point, and \d* matches zero or more digits. "$" matches the end of the string.

Upvotes: 1

Related Questions