7
votes

I am using WPF's TextBox with a binding on the Text property to a double on my ViewModel.

My XAML looks like this:

<TextBox Text="{Binding Path=MyDoubleValue, StringFormat=N2, UpdateSourceTrigger=PropertyChanged}" />

Unfortunately when I switch UpdateSourceTrigger to PropertyChanged and type value 12345, I get 12,354.00 (EDIT: notice the 5 before the 4). This is a result of keeping cursor in the same place after adding , between 2 and 3 by the .NET formatter.

How can I use StringFormat with UpdateSourceTrigger set to PropertyChanged?

Note: This is only happening in .NET 4.

1
Is 12,345.00 not what you'd expect when using StrngFormat N2? What do you expect?Jens
Yes exactly, but instead of getting that I have 12,354.00.bartosz.lipinski
The format string will not cause the digits to switch like that, there must be something else going onBen Robinson
@BenRobinson have you tried it? It's surprising and buggy.Ray
Not in WPF but 12345.ToString("N2") returns 12,345.00. Are you saying there is some weird string.format bug that is specific to WPF?Ben Robinson

1 Answers

10
votes

Usually you don't want UpdateSourceTrigger to be PropertyChanged on a TextBox.Text binding because this triggers the Validation and Change notification every time a key is pressed.

If you are doing this only so that if the user hits Enter it will save the value before processing the save command, then I'd suggest hooking into the PreviewKeyDown event and manually updating the source if the key pressed was Enter (Usually I make this an AttachedProperty)

private void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        var obj = sender as UIElement;
        BindingExpression textBinding = BindingOperations.GetBindingExpression(
            obj, TextBox.TextProperty);

        if (textBinding != null)
            textBinding.UpdateSource();
    }
}

But with that being said, if you still wanted to use UpdateSourceTrigger=PropertyChanged, then consider using the formatting when displaying the value, but remove it while the user is editing it.

<TextBox>
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Text" Value="{Binding Path=MyDoubleValue, StringFormat=N2}" />
            <Style.Triggers>
                <Trigger Property="IsFocused" Value="True">
                    <Setter Property="Text" Value="{Binding Path=MyDoubleValue, UpdateSourceTrigger=PropertyChanged}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>