简体   繁体   English

如何在ViewModels之间进行通信?

[英]How to Communicate between ViewModels?

I'm building my first WPF and MVVM application. 我正在构建我的第一个WPF和MVVM应用程序。 I have 3 views (with 3 corresponding ViewModels) 我有3个视图(3个对应的ViewModels)

1) MainWindow (Window) 1)MainWindow(窗口)

2) ViewClients (UserControl) 2)ViewClients(UserControl)

3) ViewModClient (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. 在Clients ViewModel中,我有一个属性SelectedClient ,它跟踪视图中DataGrid上的选定客户端。 In this view, I also have a button related with an ICommand defined in MainWindow ViewModel. 在这个视图中,我还有一个与MainWindow ViewModel中定义的ICommand相关的按钮。 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. 我使用CommandParameter告诉mainWindow ViewModel创建哪种视图并保持viewmodel与视图知识隔离。 This works great. 这非常有效。

Now the problem: 现在的问题是:

In the ModClient ViewModel I need to load the client's data. 在ModClient ViewModel中,我需要加载客户端的数据。 So how do i relate this with the SelectedClient from Clients View while keeping the MVVM pattern? 那么如何在保持MVVM模式的同时将其与Clients View中的SelectedClient联系起来呢? (I can only use one CommandParameter and it's already used) (我只能使用一个CommandParameter并且已经使用过了)

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 ): 所有MVVM框架都有一个消息传递总线,允许进行VM间通信,因此只需获得一个好的框架,任务就会变得如此简单( Simple MVVM Toolkit ):

Source VM: 源VM:

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

Receiving VM: 接收VM:

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

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

Caliburn.Micro for instance, got an built in IEventAggregator which allows you to create Eventmanagers which can be subscribed too. 例如,Caliburn.Micro有一个内置的IEventAggregator ,它允许你创建可以订阅的Eventmanagers。 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. 如果您使用多个ViewModel订阅此特定EventAggegrator,则可以定义可以从已订阅此EventAggregator的所有ViewModel发布和接收的消息。

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: 以下只是一个简短的实现,并显示,如果您使用像Caliburn.Micro这样的框架,ViewModel之间的通信会有多简单:

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. 但是,如果您有任何疑问,请告诉我,我会详细介绍。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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