How to avoid proxy properties in a ViewModel to access properties of the Model in MVVM?

Daljit Singh 261 Reputation points
2020-04-29T11:31:20.733+00:00

I have come accross this problem while developing my UWP application. It seems that the community advice to implement UWP app is to follow the MVVM pattern. So in my code I have a ViewModel like the following:

public class MyViewModel : ViewModelBase
{
    private Model _model;

    public MyViewModel()
    {
        this.Model = model;
    }
    public Model Model 
    {
        get; set;
    }
}

In this way I am able to access my Model from my view and simply bind properties like property={Binding Model.Property}. This works fine however when I change my property in the Model obviously the UI does not get updated. What I could do instead would be reimplement each property of Model in ViewModel (which implements INotifyPropertyChanged interface so each time a property is updated the UI is notified) through a proxy property like the following:

public ModelProperty
{
    get { return this.Model.Property; };
    private set;
}

Doing this would require a lot of effort (since my Model has a lot of properties) and I would just be duplicating my code. The alternative would to implement the INotifyPropertyChanged interface in my Model and then expose the model like above in my view model. However, this seems to against the paradigms of MVVM.

So my question is what is the best way to avoid the need of proxy properties in my ViewModel?

Universal Windows Platform (UWP)
0 comments No comments
{count} vote

Accepted answer
  1. Richard Zhang-MSFT 6,936 Reputation points
    2020-04-30T02:13:08.533+00:00

    Hello,​

    Welcome to our Microsoft Q&A platform!

    In UWP, if you need to bind the property to notify the UI when it changes, then inheriting the INotifyPropertyChanged interface is a necessary step.

    It's just that there will be some changes in the way we write attributes. Your Model and _model properties are not related, you can try to write:

    public class MyViewModel : ViewModelBase
    {
        private Model _model;
        public Model Model
        {
            get => _model;
            set
            {
                _model = value;
                // OnPropertyChanged();
            }
        }
    }
    

    The same wording can be used on specific properties of Model:

    public class Model : INotifyPropertyChanged
    {
    
        private string _property;
        public string Property
        {
            get => _property;
            set
            {
                _property = value;
                OnPropertyChanged();
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    Thanks.


1 additional answer

Sort by: Most helpful
  1. Xiaodi Yan 876 Reputation points MVP
    2020-05-01T02:32:51.48+00:00

    I prefer to create another viewmodel for your model. Let's say your model's name is MyModel. If you want to update the UI for each property of MyModel, every property should implement INotifyPropertyChanged. No need to create them again in the viewmodel. In this case, feel free to create a MyViewModel which has the same properties but implements INotifyPropertyChanged. Then have a mapper to convert MyModel to the new MyViewModel. Then include it in your current viewmodel. That's just a nested viewmodel.

    Basically, most of the mvvm frameworks for uwp have a base class, eg, BindableModel, which looks like a light viewmodel(supports INotifyPropertyChanged but may not have lifecycle events). You could just inherit it to implement your bindableModel to make the life easier.