TextBox not updating properly when decimal point is input

886 views Asked by At

I'm having some strange behavior that I can't quite figure out. I have a text box bound to a string property (that represents a numeric value). The getter should be formatting my string to include 4 decimal digits. This much works but gives the user non-intuitive surprise when entering a number with decimal values.

Example: If the user wanted to enter 5.1, they type 5 -> . -> 1 resulting in the TextBox formatting to "5.0000"->"5..0000"->"5.1.0000"

So I added additional logic to replace any sequential decimal points with a single decimal point. This is where my strange issue have started appearing. A user can enter "5.....1" and the UI does not seem to update with the removal of the sequential decimal points. However typing any character between those decimal points triggers it to correctly remove sequential decimal points:

Example: Typing a 2 before the last decimal point ("5....2.1") results in "5.2.1", which is what I expect.

If I step trough the code, the returned value always seems to be correctly formatted with no sequential decimal points. However the UI still displays "5.....1". The UI doesn't seem to update if I edit the decimal points directly (either typing more or deleting existing ones), however typing or deleting a character in between them triggers the expected update.

This is the property in the ViewModel:

Private _valueString As String
Public Property ValueString As String
    Get
        Dim formattedString As String = Double.NaN.ToString
        Dim tempDouble As Double
        Dim rgx As New Regex("\.+")

        If Double.TryParse(_ValueString, tempDouble) Then
            formattedString = tempDouble.ToString("F4")
            formattedString = rgx.Replace(formattedString, ".")
        Else
            formattedString = rgx.Replace(_valueString, ".")
        End If

        Return formattedString
    End Get
    Set(value As String)
        Dim rgx As New Regex("\.+")
        _ValueString = rgx.Replace(value, ".")

        NotifyPropertyChanged("ValueString")
    End Set
End Property

XAML:

<TextBox Text="{Binding ValueString, UpdateSourceTrigger=PropertyChanged}" />

Any ideas on what is causing it to not update? Why are users able to enter multiple decimal points in a row?

2

There are 2 answers

0
fantaztig On

Try using Text="{Binding ValueString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

Apart from that I think you should just bind the Textbox to a double Property and use a validator so that input thats unable to parse as double is not set at all.

0
kenjara On

I would set your updatesourcetrigger to LostFocus (default) and set up the following in the textbox's textchanged event. This will allow you to continue entering numbers after the decimal place. If there is no decimal place on the end it will update just like if you had set the trigger to PropertyChanged.

The update source function is manually doing what the trigger would fire.

For the sake of this example my textbox is called txbAmount.

VB

Private Sub txbAmount_TextChanged(sender As Object, e As TextChangedEventArgs)
        If Me.txbAmount.Text IsNot Nothing Then
            If Me.txbAmount.Text.Count() > 0 Then
                If Me.txbAmount.Text.Last() <> "."C Then
                    Me.txbAmount.GetBindingExpression(TextBox.TextProperty).UpdateSource()
                End If
            End If
        End If
    End Sub

C#

private void txbAmount_TextChanged(object sender, TextChangedEventArgs e)
    {
        if (this.txbAmount.Text != null)
        {
            if (this.txbAmount.Text.Count() > 0)
            {
                if (this.txbAmount.Text.Last() != '.')
                {
                    this.txbAmount.GetBindingExpression(TextBox.TextProperty).UpdateSource();
                }
            }
        }
    }