WPF - MVVM - Textbox getting out of sync with viewmodel property

.net, data-binding, mvvm, viewmodel, wpf

Solution

This is nothing but a bug in the framework. The `Text` property in the `TextBox` does get your new value but the GUI is now out of sync with its own `TextProperty`. This also happends for any `ItemsControl` when you want to cancel a change of `SelectedItem` from the ViewModel and it's really annoying.

This bug doesn't happend when you use explicit `Binding` though so this can be used as a workaround.

Xaml

<TextBox Text="{Binding Path=MyName,
                        UpdateSourceTrigger=Explicit}"
         TextChanged="TextBox_TextChanged"/>

Code behind

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

To verify that the TextBox GUI indeed is out of sync, just observe the value of `TextBox.Text`. The `TextBox` will say "123456789___0" for example while `TextBlock` says "123456789".

<StackPanel>
    <TextBox Name="myTextBox"
             Text="{Binding Path=MyName,
                            UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding ElementName=myTextBox, Path=Text}"/>
</StackPanel>

Problem

I have a WPF view with a TextBox, binding the Text field to a ViewModel with UpdateSourceTrigger set to PropertyChanged. In the property setter in the ViewModel, I have a simple check to prevent the text from exceeding 10 characters: ``` <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" /> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); this.DataContext = new MainViewModel(); } } public string Name { get { return _Name; } set { if (_Name != value) { if (value.Length <= 10) { _Name = value; } RaisePropertyChanged("Name"); } } } ``` If the value isn't set, I still RaisePropertyChanged (which simply fires PropertyChanged). The problem is that when I type in the 11th character in the UI, I don't update _Name. I fire PropertyChanged, and I can see the get accessor get called and it returns the string with only 10 characters. However, my TextBox doesn't reflect this; it still shows the string with 11 characters. On top of that, is that if on the 11th character I change the text in the setter to "ERROR", and fire property changed, the TextBox DOES update to show the altered text. So why is it that if I alter the text in the setter back to the previous value, the UI doesn't reflect this? I know there are alternative ways of handling max characters, but why won't this work?

Original source