MVVM Best Practices: communication between view models

走远了吗. 提交于 2021-02-18 17:56:43

问题


My simplified program structure looks like this:

public class Manager
{
    public Item MyItem { get; set; }

    public void Recalculate(){ ... } 
}

public class Item
{
    public string SomeProperty { get; set; }
}

public class ManagerViewModel
{
    public Manager Model { get; set; }

    public ItemViewModel MyItem { get; set; }
}


public class ItemViewModel
{
    public Item Model { get; set; }

    public string SomeProperty
    {
        get => Model.SomeProperty;
        set 
        { 
            Model.SomeProperty = value;
            RaisePropertyChanged("SomeProperty");
        }
    }
}

When SomeProperty gets changed in ItemViewModel, I want Recalculate() to get triggered inside Manager.

Do I:

A) Have a PropertyChangedListener inside ManagerViewModel which listens for Property changes inside it's MyItem, and then tells it's Model to Recalculate()

B) Allow ItemViewModel to have access to Manager, so it can manually tell Manager to run Recalculate()

..

(B) seems kind of anti-pattern-ish... shouldn't each ViewModel only really be concerned with it's own Model? (A) has it's own issues -- I need to use this sort of 'Recalculation' structure a lot, and it seems having these PropertyChangedListeners all over the place is kind of messy. I realise there's a few different ways of going about this, but I'm just wondering what the 'best practice' is in this case.


回答1:


As confirmed by Ed Plunkett, 'option A' is the best approach, as it separates the concerns of the ViewModels and Models.

ItemViewModel is only concerned with it's own Model, and it just notifies whoever's listening that it's properties have been changed.

ManagerViewModel listens for changes inside ItemViewModel, and then executes Recalculate() inside it's own model.

//Models

public class Manager
{
    public Item MyItem { get; set; }

    public void Recalculate(){ ... } 
}

public class Item
{
    public string SomeProperty { get; set; }
}

//ViewModels

public class ManagerViewModel
{
    public Manager Model { get; set; }

    public ItemViewModel MyItem { get; set; }

    public ManagerViewModel()
    {
        //Listen for property changes inside MyItem
        MyItem.PropertyChanged += ItemPropertyChanged;
    }

    //Whenever a Property gets updated inside MyItem, run Recalculate() inside the Manager Model 
    private void ItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Model.Recalculate();
    }
}


public class ItemViewModel
{
    public Item Model { get; set; }

    public string SomeProperty
    {
        get => Model.SomeProperty;
        set 
        { 
            Model.SomeProperty = value;
            RaisePropertyChanged("SomeProperty");
        }
    }
}



回答2:


There's nothing wrong with making your Model(s) observable by adding INotifyPropertyChanged to them also. Then you can listen to the models you're bound to. In many projects I prefer to have a static data set layer, which publishes the list of models from a store and those models are all observable. This means they can be bound to and since the store is the same source any ViewModels etc can bind to them and become updated system wide. Looks like you're on the right track so don't second guess yourself. Making things observable, downright to the model, isn't bad or considered bad practice. I personally prefer it.



来源:https://stackoverflow.com/questions/46984421/mvvm-best-practices-communication-between-view-models

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!