WPF TextBox value does not change to OnPropertyChanged

I have a TextBox whose value is bound to the ViewModel property:

<TextBox Name="txtRunAfter" Grid.Column="4" Text="{Binding Mode=TwoWay, Path=RunAfter}" Style="{StaticResource TestStepTextBox}"/> 

Set and get worked fine until I tried to add some validation when the value is set:

  private int _runAfter = 0; public string RunAfter { get { return _runAfter.ToString(); } set { int val = int.Parse(value); if (_runAfter != val) { if (val < _order) _runAfter = val; else { _runAfter = 0; OnPropertyChanged("RunAfter"); } } } } 

Despite the fact that OnPropertyChanged has been reached (I uploaded it), the View does not change. How can I do this job?

Thank you Jose Tavares

+6
wpf mvvm binding textbox
source share
3 answers

The problem is that you are updating the source for Binding , and Binding updating your property. WPF does not actually check your property value when it raises the PropertyChanged event in response to a Binding update. You can solve this problem by using Dispatcher to delay the propagation of events in this thread:

 set { int val = int.Parse(value); if (_runAfter != val) { if (val < _order) { _runAfter = val; OnPropertyChanged("RunAfter"); } else { _runAfter = 0; Dispatcher.CurrentDispatcher.BeginInvoke( new Action<String>(OnPropertyChanged), DispatcherPriority.DataBind, "RunAfter"); } } } 

Update:

I noticed that Binding on your TextBox uses the default UpdateSourceTrigger , which happens when the TextBox loses focus. You will not see the text change to 0 until the TextBox loses focus with this mode. If you change it to PropertyChanged , you will see that this happens immediately. Otherwise, your property will not be set until your TextBox loses focus:

 <TextBox Name="txtRunAfter" Grid.Column="4" Text="{Binding RunAfter, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TestStepTextBox}"/> 
+5
source share

A few things I noticed here.

Unless you have a good reason to set the RunAfter property as a string, there is no reason why it cannot be int. This would save you casting to the setter (as well as hiding a possible InvalidCastException if the user enters something non-integer in the field).

Secondly, the call to OnPropertyChanged () should occur outside the internal if statement, for example:

 if(_runAfter != val) { if(val < _order) _runAfter = val; else _runAfter = 0; OnPropertyChanged("RunAfter"); } 

Since the _runAfter locale is updated in both paths of the conditional expression, OnPropertyChanged () must be called regardless of the branch received. Hope this helps you in the right direction!

+3
source share

I had the same situation. I wrote the following and it worked.

<TextBox Grid.Column="3" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Text="{Binding Path=FirstName}"></TextBox>

AND

 public string FirstName { get { return _client.FirstName; } set { if (value == _client.FirstName) return; else _client.FirstName = value; OnPropertyChanged("FirstName"); } } 
+1
source share

All Articles