Using the MVVM INotifyPropertyChanged Model Without Notifying ViewModel

I am trying to use MVVM for the first time. I have a Windows Phone (Mango) application that has a model class, presentation model class and xaml view page. I have controls (text fields) attached to a virtual machine, and the virtual machine is attached to a model.

Both the model and the view model implement INotifyPropertyChanged . The implementation I'm using is copied, so I can use it to try and figure out what I'm doing with INPC. Here is the code that is specified in both classes:

 public event PropertyChangedEventHandler PropertyChanged; private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } 

I have one property in the model class that can be set manually (from a text field) or calculated (by changing one of the other properties). Let me name this result.

If I change one of the other properties and follow the steps, INPC is called both in the changed property and in the translation in the Model class, although PropertyChanged is null , so part of the code is skipped. Then, in the virtual machine, the property that was changed goes through this the INPC class (as part of the access set), and this time the PropertyChanged not null , so the PropertyChanged method is called. However, for a Result property, INPC is not raised (this property does not have an INPC called by another property accessor).

Here is one of the properties in the Model that is not a calculated property:

 public int AgeSetting { get { return (int)GetValueOrDefault(AgeSettingKeyName, AgeSettingDefault); } set { AddOrUpdateValue(AgeSettingKeyName, value); Calculate(); } } 

Here is the Calculated Value property in the Model.

 public int PointsSetting { get { return (int)GetValueOrDefault(PointsSettingKeyName, PointsSettingDefault); } set { AddOrUpdateValue(PointsSettingKeyName, value); } } 

From ViewModel, here are both properties:

 public int Age { get { return person.AgeSetting; } set { person.AgeSetting = value; NotifyPropertyChanged("Age"); } } public int PointsAllowed { get { return person.PointsSetting; } set { person.PointsSetting = value; NotifyPropertyChanged("PointsAllowed"); } } 

This has never been done before, I expected that INPC should go from the model class to the VM class to the user interface. This does not seem to work.

I know that the Result (calculate) property is changing, since I can go from the page and return, and the newly displayed value is correct. I just don’t know how to get from the calculated value in the model, the presentation model and before the presentation.

Thanks for any suggestions.

+4
source share
4 answers

If the value of the computed property changes, also raise the PropertyChanged event for this property. This means that when a single property changes, there may be events triggered for several properties.

In addition, if it is possible / smart in your design, you can directly bind it to the model properties and make the model a ViewModel property. This is a reduction in code maintenance by a lot.

+5
source

For properties that depend on the values ​​of other properties, the programmer must notify about the change of several properties.

Given a class with three properties β€” Score, Multiplier, and Total β€” where Total depends on the values ​​of Score and Multiplier, I can write the class as follows:

 public class ViewModel { private int score; public int Score { get { return this.score; } set { if (this.score != value) { this.score = value; // Notify that this property has changed NotifyOfPropertyChange(() => this.Score); // Notify that a dependant property has changed NotifyOfPropertyChange(() => this.Total); } } } private int multiplier; public int Multiplier { get { return this.multiplier; } set { if (this.multiplier != value) { this.multiplier = value; // Notify that this property has changed NotifyOfPropertyChange(() => this.Multiplier); // Notify that a dependant property has changed NotifyOfPropertyChange(() => this.Total); } } } public int Total { get { return this.Score * this.Multiplier; } } } 

You will notice, for example, that when I set the value to Score, I will notify that both Score and Total have changed. Your specific NotifyOfPropertyChange implication will be different from mine, but the central idea is the same. Since Total is dependent on the values ​​of other properties, it never notifies about it. Instead, the responsibility for what Total depends on is the responsibility of the notice.

+3
source

In the model, the NotifyPropertyChanged method is called in the installer of the computed property. Some logic in your application should update the model. Make sure the ViewModel is subscribed to this event. This is very important because I think this is exactly what you are missing here.

Then, in the EventHandler in the ViewModel that was subscribed to the Models on PropertyChanged event, change the corresponding value of the ViewModel property (here the method in the view model updates the property in the view model) that the interface interface to.

+1
source

It looks like you did not implement the INotifyPropertyChanged interface in the model class. Without this, your event handler will be null when called.

 public class ViewModel : INotifyPropertyChanged { // Stuff } public class Model : INotifyPropertyChanged { // Stuff } 

Also check out my blog here about some MVVM stuff. I have some lessons as well as some ways to run Inotify without using string values ​​(use reflection instead).

+1
source

All Articles