Reputation:
Assume a model that comes with a property called Value
. The model implements INotifyPropertyChanged
. Next, assume a view model that knows the model and offers itself a property Value
to a imaginary view. This view model is implemented as follows:
View model code snippet
public int Value
{
get {
Model.Value;
}
set {
if(value != Model.Value) {
Model.Value = value;
OnPropertyChanged();
}
}
}
I.e. the whole purpose of the view at this point is to directly pass a property of the model to the view.
The view model is registered to the model's PropertyChanged
events. Every time Value
of the model changes, the view model notices the change and triggers a PropertyChanged
event itself so that a view that binds to the view model's property Value
knows to update itself.
This leads to multiple PropertyChanged
calls If one changes the model via the view model:
Model.Value = value;
Value
due to OnPropertyChanged();
The only solution that comes to my mind is to completly separate the view model from the model. This includes holding a complete clone of the model's data. This way I can avoid the first call of PropertyChanged
. Because I'm able to compare the value of the view model with the value of the model I can distinguish between different sources of the change (i.e. view model changed model or model was changed by another source).
Note that the view model is far more complex. Merging the model with the view model is not a solution.
Upvotes: 0
Views: 164
Reputation: 37059
The viewmodel should be in charge of updating the view and updating the model.
You've essentially identified the reason why the model shouldn't implement INotifyPropertyChanged
, and shouldn't do anything that requires it to. There isn't a clean, normal MVVM way to do what you're trying to do. That suggests that you're doing MVVM wrong. MVVM isn't holy writ, of course, but it does work well and what you're doing instead has already gotten you into trouble. You've created a problem you didn't need to create, and there are no good solutions to it. The answer isn't to choose the least-worst solution; it's to go back and eliminate the problem from the design.
This design is fundamentally ill-conceived and any attempt to salvage it by adding further complexity will be a mess. It was worth doing because you learned from it, but it's not worth investing any more time in.
The answer to your literal question, "how to implement a viewmodel [property] that wraps a model's property", is:
Just like you did it in your public int Value
example, but without the model implementing INotifyPropertyChanged
.
Upvotes: 2
Reputation: 247133
If the view model is already registered to the model's property changed and in turn raises its own property change then there is not a need for OnPropertyChanged()
in the property of the view model.
Remove OnPropertyChanged()
ViewModel code would look like.
public int Value {
get {
return Model.Value;
}
set {
if(value != Model.Value) {
Model.Value = value;
}
}
}
Upvotes: -1