I'm currently working on a project which leverages the MVVM pattern, and have came across this scenario.
Supposed a class Model : INotifyPropertyChanged contains some properties, for example
public class Model : INotifyPropertyChanged
{
private string rabbit;
public string Rabbit
{
get { return rabbit; }
setter { rabbit = value; OnPropertyChanged("Rabbit"); }
}
}
Now, I wish to write a ViewModel which wraps around Model, exposing the properties of Model together with additional properties (commands, etc).
The problem comes when writing the getters and setters for the properties already existing in Model. I have commented out the specific portion of the code.
public class ViewModel : INotifyPropertyChanged
{
private Model modelObject;
public string Rabbit
{
get { return modelObject.rabbit; }
setter
{
modelObject.rabbit = value;
OnPropertyChanged("Rabbit"); // Should OnPropertyChanged be called here?
}
}
public ViewModel(Model modelObject)
{
this.modelObject = modelObject;
}
}
I am not sure if I should call OnPropertyChanged again in the ViewModel. Since the View binds to the ViewModel but should not be able to access the model, it seems only logical to do so.
(P.S. the reason I made my model observable is the same model will be used elsewhere apart from the GUI in the same memory space, where there is also a need to be notified of changes to the model.)
This is one of the basic issues with MVVM, with a few different philosophies about how to solve it.
Your current approach is fine, and very pure MVVM. The drawback is the amount of work required.
I am not sure if I should call OnPropertyChanged again in the ViewModel.
You will have to, the INPC of the Model does not help the databinding. You will also have to subscribe your ViewModel to the Model.PropertyChanged and echo these changes in the VM.
Another, acceptable, approach is to expose the Model as a public property (with INPC) and bind with <TextBlock Text="{Binding Model.Rabbit}" />
You can have a look at the picture here. Notice the large block of arrows in the top-right corner, these represent the various solutions to this problem.