Access properties from one view model in another

2019-04-02 07:55发布

问题:

My WPF application follows the MVVM pattern. There are three views:

  • MainWindow
    • LoginView
    • ProjectsView

LoginView and ProjectsView are user controls imported by the MainWindow. Both views have their view model assigned. LoginViewModel defines a property ProjectList which is set by calling a webservice. Now LoginViewModel needs access to the ProjectList property and others.

I am aware that one solution might be a redesign so that there is only one view and one view model. I would do that as a backup solution but I would favor not to do so.

How should this be done? Should I use some kind of EventAggregator like in Prism? Or are there other ways to do this?

回答1:

So if i understood clearly, ProjectList property should be accessed from both 'LoginViewModel' and 'ProjectsViewModel'. I'd try to implement it in the 'MainViewModel' so child viewmodels can access it in a natural way.

An IEventAggregator is like a box in which you can add events, or find and subscribe to one, so i would say it's not what you need. Anyway, you could register your custom interface (box type) in the UnitySingleton.Container, which would expose ProjectList for it to be accessible everywhere. This approach makes a lot of sense when modules, which are separate assemblies, need to communicate whith each other. If this is overkill or not in your case is something you should decide, i'd personally go with the 'put it in the mainviewmodel' option.

-- Sample -- (not tested)

public class MainViewModel : ViewModelBase
{
    public MainViewModel()
    {
        LoginVM = new LoginViewModel(this);
        ProjectsVM = new ProjectsViewModel(this);
        RetrieveProjectList();
    }

    public LoginViewModel LoginVM { get; private set; }

    public ProjectsViewModel ProjectsVM { get; private set; }

    public object ProjectList { get; private set; }

    private void RetrieveProjectList()
    {
        ProjectList = ....
    }
}

It's pretty simple as you see, LoginVM and ProjectsVM will hold a reference to the MainViewModel that created them, therefore giving them access to ProjectList.



回答2:

How should this be done? Should I use some kind of EventAggregator like in Prism? Or are there other ways to do this?

Here are a few ideas:

  • You can create a view-model class that both view-models inherit from. This base class will contain the shared properties.
  • Create a static class that contains the shared properties.
  • Using dependency injection, create a class that contains the properties, register it as a singleton in your container and inject it into your view-model's ctors.

Also, I believe that the EventAggregator is best suited for communicating between modules/assemblies. In your example, it seems like everything is in the same assembly.