0
votes

I'm building my first WPF and MVVM application. I have 3 views (with 3 corresponding ViewModels)

1) MainWindow (Window)

2) ViewClients (UserControl)

3) ViewModClient (UserControl)

In Clients ViewModel I have a property SelectedClient that keeps track of the selected client on a DataGrid in the view. In this view, I also have a button related with an ICommand defined in MainWindow ViewModel. I resolve it with this binding:

Command="{Binding Path=DataContext.CreateViewsCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" CommandParameter={x:Type local:ViewModClient}

I use CommandParameter to tell the mainWindow ViewModel which kind of view to create and keep the viewmodel isolated from views knowledge. This works great.

Now the problem:

In the ModClient ViewModel I need to load the client's data. So how do i relate this with the SelectedClient from Clients View while keeping the MVVM pattern? (I can only use one CommandParameter and it's already used)

2
Maybe use an EventAggregator of some form? You could raise an event from your ViewClients VM and subscribe to it in the ViewModClient VM. - Daniel Kelley
Thank you for your answer. Can you give me some sample code? Maybe you can post it like a suggest answer. - ericpap
Check out the MVVM Light Toolkit, it has built-in messaging support mvvmlight.codeplex.com - reggaeguitar
Also consider Catel. It is a fully-featured MVVM framework and comes with on-line templates and a great getting started guide (catelproject.atlassian.net/wiki/display/CTL/…). This means that you can just try and experience it. It contains several methods to communicate between view models: 1) Attribute based communication 2) Message mediator - Geert van Horrik

2 Answers

1
votes

Caliburn.Micro for instance, got an built in IEventAggregator which allows you to create Eventmanagers which can be subscribed too. If you subscribe to this particular EventAggegrator with several ViewModels, you can define Messages that can be published and received from all ViewModels that have subscribed to this EventAggregator.

The following is just a short implementation and shows, how easy the communication between ViewModels can be, if you use a framework like Caliburn.Micro:

class ViewModel1 : PropertyChangedBase
{
    private IEventAggregator _Event;
    public ViewModel1(IEventAggregator events)
    {
        _Event = events;
        _Events.Publish(new TestEvent(5));
    }
}

class ViewModel2 : PropertyChangedBase, IHandle<TestEvent>
{
    private IEventAggregator _Events;
    public ViewModel2(IEventAggregator events)
    {
        _Events = events;
        _Events.Subscribe(this);
    }

    public void Handle(TestEvent message)
    {
        // do something with the incoming message
    }
}

class TestEvent
{
    public int foo { get; set; }
    public TestEvent(int someint)
    {
        foo = someint;
    }
}

It should be pretty self explanatory. However, if you have any questions, please let me know and I will get into more detail.

1
votes

Typically this is done by using messaging.

All MVVM frameworks have a messaging bus to allow Inter-VM communication so just get a good framework and the task will get as simple as this (Simple MVVM Toolkit):

Source VM:

SendMessage(MessageTokens.SomeToken, new NotificationEventArgs<string>
            (MessageTokens.SomeToken, "MyMessage"));

Receiving VM:

RegisterToReceiveMessages<string>(MessageTokens.SomeToken, OnMessageReceived);

private void OnMessageReceived(object sender, NotificationEventArgs<string> e)
{
    // Code to execute upon message reception.
}