I implemented INotifyPropertyChanged
as recommended by many threads.
Implementation 1
public class Notifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string pName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(pName));
}
}
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("name_changed"); }
}
}
And the viewmodel consists of the model and command to make changes to model properties.
public class ViewModel : Notifier
{
private Model _model;
public Model Model
{
get { return _model; }
set { _model = value; OnPropertyChanged("model_changed"); }
}
private ICommand _cmd;
public ICommand Command
{
get { return _cmd; }
set { _cmd = value; }
}
public void ExecuteCommand(object para)
{
Console.WriteLine("Command executed");
Model.Name = "new name";
}
}
VM is then binded to the view.
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Width="100">
<TextBox.Text>
<Binding Path="Model.Name" Mode="TwoWay" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<ExceptionValidationRule></ExceptionValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
When the command is executed, the TextBox
does not get updated to new value.
However, if I implement the INotifyPropertyChanged
like this instruction, the binding works.
Implementation 2
public class Notifier : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T newValue, [CallerMemberName]string propertyName = null)
{
if (!EqualityComparer<T>.Default.Equals(field, newValue))
{
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
return true;
}
return false;
}
}
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { SetProperty(ref name, value); }
}
}
What is missed in the first method?
Please add property name like this.
public class Model : Notifier, IDataErrorInfo
{
private string name;
public string Name
{
get { return name; }
set { name = value; OnPropertyChanged("Name"); }
}
}