0

I am making a windows phone application that has a price field. As soon as the user starts to type I want update some other textboxes. I am using mvvm light so usually the property is not updated till the user leaves the textbox.

This does not work for me so I found this and implemented it but not I have a weird problem and I don't get why.

When I type in the box 50, the property first gets updated to "5" and then to "50" which is expected but when I first "." nothing is triggered, then when I type in 5 the property seems to be hit 3 times and once it is done it moves the cursor back to the begginging of the textbox.

So instead of 0.59 I get 90.5

Code Behind

private void txtPrice_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    TextBox textBox = sender as TextBox;
    textBox.Text = "";
}

private void txtPrice_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    // Update the binding source
    BindingExpression bindingExpr = textBox.GetBindingExpression(TextBox.TextProperty);
    bindingExpr.UpdateSource();
}

In Model

 /// <summary>
    /// The <see cref="Price" /> property's name.
    /// </summary>
    public const string PricePropertyName = "Price";

    private decimal price = 0.00M;

    /// <summary>
    /// Sets and gets the Price property.
    /// Changes to that property's value raise the PropertyChanged event. 
    /// </summary>
    public decimal Price
    {
        get
        {
            return price;
        }

        set
        {
            if (price == value)
            {
                return;
            }

            RaisePropertyChanging(() => Price);
            price = value;
            RaisePropertyChanged(() => Price);
        }
    }

XAML

<TextBox x:Name="txtPrice" Margin="157,16,102,0" TextWrapping="Wrap" VerticalAlignment="Top" InputScope="Number" Text="{Binding WeightConversion.Price, Mode=TwoWay, UpdateSourceTrigger=Explicit}" Tap="txtPrice_Tap" TextChanged="txtPrice_TextChanged" />
Community
  • 1
  • 1
chobo2
  • 83,322
  • 195
  • 530
  • 832

1 Answers1

2

The problem is that "." by itself is not a valid decimal so when the binding try to update Price it fail. Latter when you enter ".5" it consider it a valid number and update the value of Price but when price raise property changed and it is converted back to Text it is converted to 0.5 which force a "programmatic" update of the text box and will reset the cursor to the first position.

To fix this problem the best solution I see is probably use a string property to back up the Price and update the decimal value "manually":

private decimal price = 0.00M;

/// <summary>
/// Sets and gets the Price property.
/// Changes to that property's value raise the PropertyChanged event. 
/// </summary>
public decimal Price
{
    get
    {
        return price;
    }

    set
    {
        if (price == value)
        {
            return;
        }

        RaisePropertyChanging(() => Price);
        price = value;
        RaisePropertyChanged(() => Price);


        this.PriceStr = this.Price.ToString();

    }
}


private string priceStr=0.00M.ToString();
/// <summary>
/// Sets and gets the Price property.
/// Changes to that property's value raise the PropertyChanged event. 
/// </summary>
public string PriceStr
{
    get
    {
        return priceStr;
    }

    set
    {
        if (priceStr == value)
        {
            return;
        }


        priceStr = value;

        isPriceAValidStr=decimal.TryParse(this.PriceStr, out price);


        RaisePropertyChanged(() => Price);
        RaisePropertyChanged(() => PriceStr);
    }
}

        private bool isPriceAValidStr = true;

and change you binding of Text to PriceStr.

Also there is another problem, even with InputScope="Number" there is still some way to enter text in your text box:

  • by using the harware keyboard for phone which have one (in the emulator you can simulate that by pressing the page down key and then you will be able to use your keyboard to enter text). To fix that you can register for the key_down event and do some condition check on e.Key and reject all key that you don't want by setting e.Handled = true;. Also you can use this to also prevent user to enter two time a .
  • by copying some text from another text box were text is enabled (probably should just also removed all invalid letters in TextChanged)
Benoit Catherinet
  • 3,335
  • 1
  • 13
  • 12
  • Did not know that there are devices taht have a hardware keyboard. I will do that then, was wondering if I have to do checks for those kind of things on phones like you have to do with web sites. – chobo2 Sep 29 '13 at 23:26
  • I haven't seen any windows phone 8 with hardware keyboard but they were a couple of windows phone 7 with one. – Benoit Catherinet Sep 29 '13 at 23:47