2

I have a WPF textbox that is databound. I need to restrict the user input on the textbox so that it only accepts numbers and a single period (For displaying decimals).

I know I can handle this in "Winforms" way and validate each input on KeyPress event, but I was wondering if there was a cleaner and maybe even proper way to do this in WPF (especially since I am databinding the textbox).

TtT23
  • 6,876
  • 34
  • 103
  • 174

3 Answers3

4

Use ValidationRules provided by WPF.

The xaml would be:

<TextBox>
    <TextBox.Text>
        <Binding Path="Name">
            <Binding.ValidationRules>
                <ExceptionValidationRule />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

The code for the textbox property would be (used regex for the validation):

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        if (!Regex.IsMatch(value, @"^((?:[1-9]\d*)|(?:(?=[\d.]+)(?:[1-9]\d*|0)\.\d+))$"))
        {
            throw new ApplicationException("Please enter only numbers/decimals.");
        }
    }
}

Source: Validation in WPF


The regex given above: ^((?:[1-9]\d*)|(?:(?=[\d.]+)(?:[1-9]\d*|0)\.\d+))$ can be tested at this Rubular link

The regex would match these:

1.2
22522
0.33
3.90000

but not these: (you could tweak the regex to allow some of them)

.999
23.35.1343
03423.23423
Kash
  • 8,799
  • 4
  • 29
  • 48
  • The regex you gave me doesn't even compile It says Nested Quantifier+ – TtT23 Aug 31 '12 at 05:28
  • Try the updated one now. I had a `*` quantifier after the `+`quantifier which Rubular does not care but the .NET Regex does. – Kash Aug 31 '12 at 05:49
3

Databinding will affect the values passed to/from the object you're databound to. To stop the user from pressing keys you either need to use a masked text box (in winforms, not sure about WPF) or you need to handle the KeyPressedEvent in the textbox and stop the keys you don't want pressed from happening.

I have used the code below to only allow digits and one decimal

private void textBoxPrice_KeyPress( object sender, KeyPressEventArgs e )
        {
            if( !char.IsControl( e.KeyChar )
                && !char.IsDigit( e.KeyChar )
                && e.KeyChar != '.' )
            {
                e.Handled = true;
            }

            // only allow one decimal point
            if( e.KeyChar == '.'
                && ( sender as TextBox ).Text.IndexOf( '.' ) > -1 )
            {
                e.Handled = true;
            }
        }
Justin
  • 4,002
  • 2
  • 19
  • 21
0

just use keypress event, and validate the key press event with ascii character.

e.KeyCode >47 && e.KeyCode <58 would be restricting user not to press any letters apart from numbers.

If you need exact code sample, wait for a while :)

VIRA
  • 1,454
  • 1
  • 16
  • 25
  • Simply filtering keys still allows very invalid values such as 1.1.1.1.1.1.1.1 – dodexahedron Aug 31 '12 at 05:50
  • ah, chaps please add additional filters for the valid values. I can give all the codings right a way because I dont know your requirement fully. if you modify the range for only integers, then it wont allow dots. – VIRA Aug 31 '12 at 06:34
  • refer the below coding from @justin, its what i referred. Due to busy in work, i was unable to do. – VIRA Aug 31 '12 at 06:37