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?