WPF application using MVVM. I have a TextBox
whose Text
property is bound to a decimal
property of the view model. This property represents a currency value. I would like the TextBox
to display the data in currency format. To this end, I have set StringFormat
to "c" in the Binding
. This works as expected.
The problem is that, if SourceUpdateTrigger
is PropertyChanged
, when the user starts typing, formatting is applied after entering the first character and the caret is then positioned before the character just entered. This means that the next character will be entered before the first instead of after. If SourceUpdateTrigger
is LostFocus
then the user must shift focus to another control before the OK button is enabled, which occurs after validating the currency field.
What I was hoping to do was handle the GotFocus
and LostFocus
events, get a reference to the Binding
and change its StringFormat
property. I have no issue with this in regards to MVVM because it's a purely UI issue. The problem is that an exception was thrown and I was told that the Binding
could not be changed after being used.
I've considered various other options, including a custom converter. That didn't work though, because I couldn't work out how to use the ConverterParameter
to expose the control's IsFocused
property to the converter.
Anyone have any ideas?
You can use a data trigger in a data template to dynamically change your binding for a text box.
<DataTemplate x:Key="DataTemplate1">
<TextBox x:Name="TheTextBox"
Text="{Binding Path=ThePropertyPath, StringFormat={}{0:p0}, UpdateSourceTrigger=PropertyChanged}" />
<DataTemplate.Triggers>
<!-- Set the TextBox.Text Binding but this time leave the StringFormat off -->
<DataTrigger Binding="{Binding Path=IsKeyboardFocusWithin, ElementName=TheTextBox}" Value="True">
<Setter TargetName="TheTextBox" Property="Text" Value="{Binding Path=ThePropertyPath, UpdateSourceTrigger=PropertyChanged}" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsFocused, ElementName=TheTextBox}" Value="True">
<Setter TargetName="TheTextBox" Property="Text" Value="{Binding Path=ThePropertyPath, UpdateSourceTrigger=PropertyChanged}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>