Binding to a double with StringFormat on a TextBox

bartosz.lipinski picture bartosz.lipinski · Nov 18, 2011 · Viewed 14.5k times · Source

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.

Answer

Rachel picture Rachel · Nov 18, 2011

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>