Binding to a double with StringFormat on a TextBox

14,996

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>
Share:
14,996
bartosz.lipinski
Author by

bartosz.lipinski

dev @solana

Updated on June 07, 2022

Comments

  • bartosz.lipinski
    bartosz.lipinski almost 2 years

    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.

  • bartosz.lipinski
    bartosz.lipinski over 12 years
    Do you have any idea how to achieve something similar with converters? The perfect solution would be to have a converter which is doing formatting only if control is not focused
  • Rachel
    Rachel over 12 years
    @baalazamon You could create a StringFormat multi-converter which returns your value.ToString(converterParameter) if the control IsFocused, however I think DataTriggers is a better way to go in this case
  • epalm
    epalm almost 12 years
    For some reason, using this solution, if I type "2.5" into a blank TextBox I get "25", the decimal isn't appearing. If I reposition the cursor to anywhere except further right, then I can type decimals.
  • Bill Tarbell
    Bill Tarbell about 10 years
    @epalm the reason is logical. When sourceTrigger=PropChanged the text is evaluated as you type it. When you type "2." it will apply the double format and give you "2". This effectively means you can't type a decimal without positioning your cursor away from the right edge.
  • Kevin Cruijssen
    Kevin Cruijssen over 8 years
    Thanks Rachel, your second solution did the trick for me. @epalm & @BillTarbell I had the same issue. This can be fixed by adding a Delay=350 to the UpdateSourceTrigger=PropertyChanged Binding. (350 can be replaced with any time in ms).