简体   繁体   中英

WPF: Communication between windows on MVVM

I am struggled to understand how to let multiple windows communicating each other using MVVM pattern.

I have my parent window P and two children called C1 and C2. What I want to achieve is that when C1 changes a property that is common to P, P is notified and communicate that to C2.

I do not want to use a common ViewModel since I want to find a solution that can scale easily and I do not even want to force C1 to have the same field name of P and C2.

This would be applied to a pluggable toolkit, where me or another person could create a new component's assembly (a Window for example) and subscribe to be notified when the main window or another component changes elements in common.

Is there some kind of pattern that I am missing?

I would use Prism for that.

Here is an example:

Class which will raise the event:

public class MainViewModel
{
    public void UpdateName(string name)
    {
        Utility.EventAggregator.GetEvent<UpdateNameEvent>().Publish(name);
    }
}

Two classes will subscribe to this event:

public class Child1ViewModel
{
    public string Name { get; set; }

    public Child1ViewModel()
    {
        Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
    }

    private void UpdateName(string name)
    {
        this.Name = name;
    }
}

and

public class Child2ViewModel
{
    public string Name { get; set; }

    public Child2ViewModel()
    {
        Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
    }

    private void UpdateName(string name)
    {
        this.Name = name;
    }
}

EventAggregator which is part of Prism.Events resides here:

public class Utility
{
    public static EventAggregator EventAggregator { get; set; }

    static Utility()
    {
        EventAggregator = new EventAggregator();
    }
}

And the event is simply defined like this:

public class UpdateNameEvent : PubSubEvent<string>
{
}

Now give it a try:

static void Main(string[] args)
{
    MainViewModel mainViewModel = new MainViewModel();
    Child1ViewModel child1 = new Child1ViewModel();
    Child2ViewModel child2 = new Child2ViewModel();
    mainViewModel.UpdateName("Name1");

    Console.WriteLine(child1.Name);
    Console.WriteLine(child2.Name);
}

For this example i am using a console app. to go faster and a string parameter but you can replace that according to your needs. Be it an MVVM approach or any other pattern, you can easily implement this kind of communication.

Install Prism.Core with the help of Nuget and you will get the reference to Prism dll.

Once again: MainViewModel will Publish the event and both children will Subscribe to that event.

That's about it.

Is there some kind of pattern that I am missing?

Yes. You could use the EventAggregator in Prism or the Messenger class in MvvmLight to send a message from one window to another in a loosely coupled way. Please refer to the following links for more information about the concept.

https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

https://msdn.microsoft.com/en-us/magazine/jj694937.aspx http://dotnetpattern.com/mvvm-light-messenger

Each window know only about an event aggregator or messenger. The windows have no knowledge about or dependencies upon each other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM