Tomtom
Tomtom

Reputation: 9384

Bind TextBox to decimal-property

In my application I have a TextBox where the user can input a number beetween 1 and 10. The xaml of this TextBox looks like:

<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Center" x:Name="tbInput"/>

The property Value where the TextBox is bound to looks like:

public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(decimal), typeof(NumericUpDown), new PropertyMetadata((d, e) =>
        {
            ((NumericUpDown)d).Value = (decimal)e.NewValue;
        }));

public decimal Value
{
    get { return (decimal)GetValue(ValueProperty); }
    set
    {
        if (Value == value || value > Maximum || value < Minimum)
            return;
        SetValue(ValueProperty, value);
        OnPropertyChanged("Value");
        OnValueChanged();
    }
}

It works if the user types in a number. But if the user types in a char or a string or something else than it doesn't work. I expected that my TextBox wouldn't accept the invalid value but a breakpoint in the setter of the Value-Property is not reached.

What do I have to do to only allow numbers or to decline the user-input if it's not correct?

Upvotes: 0

Views: 876

Answers (1)

Clemens
Clemens

Reputation: 128013

The statement

((NumericUpDown)d).Value = (decimal)e.NewValue;

in the PropertyChangedCallback doesn't make sense, because it just sets the Value property another time to the same value.

You should instead move the code from the property setter to the callback. Moreover, you should not call anything but SetValue in the setter of the CLR wrapper of a dependency property. The reason is explained in the XAML Loading and Dependency Properties article on MSDN.

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register(
        "Value", typeof(decimal), typeof(NumericUpDown),
        new PropertyMetadata(
            (d, e) =>
            {
                ((NumericUpDown)d).OnValueChanged();
            }));

public decimal Value
{
    get { return (decimal)GetValue(ValueProperty); }
    set { SetValue(ValueProperty, value);}
}

In order to validate the value passed to your dependency property, you may use the DependencyProperty.Register overload that takes a ValidateValueCallback argument:

public static readonly DependencyProperty ValueProperty =
    DependencyProperty.Register(
        "Value", typeof(decimal), typeof(MainWindow),
        new PropertyMetadata((d, e) => ((NumericUpDown)d).OnValueChanged()),
        v => (decimal)v >= Minimum && (decimal)v <= Maximum);

Upvotes: 1

Related Questions