2014-04-18 368 views
0

我正在构建我的第一个WPF和MVVM应用程序。我有3次(用3周对应的ViewModels)如何在ViewModels之间进行通信?

1)主窗口(窗口)

2)ViewClients(用户控件)

3)ViewModClient(用户控件)

在客户端ViewModel我有一个属性SelectedClient跟踪视图中的DataGrid上选定的客户端。在这个视图中,我也有一个与在MainWindow ViewModel中定义的ICommand相关的按钮。 我这个结合解决它:

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

我用CommandParameter告诉主窗口视图模型样的看法,以建立和保持从知识观隔离视图模型其中。这很好。

现在的问题:

在ModClient视图模型我需要加载客户端的数据。那么我如何将这与Clients View中的SelectedClient相关联,同时保持MVVM模式呢? (我只能使用一个CommandParameter并且已经使用它)

+0

也许使用某种形式的EventAggregator?您可以从ViewClients VM引发事件并在ViewModClient VM中订阅它。 –

+0

谢谢你的回答。你能给我一些示例代码吗?也许你可以发布它像一个建议的答案。 – ericpap

+0

查看MVVM Light Toolkit,它具有内置的消息传递支持https://mvvmlight.codeplex.com/ – reggaeguitar

回答

1

Caliburn.Micro例如,有一个建于IEventAggregator,它允许你创建Eventmanagers可以是苏也订阅。如果您使用多个ViewModels订阅此特定EventAggegrator,则可以定义可从已订阅此EventAggregator的所有ViewModel发布和接收的消息。

下只有很短的执行和显示,的ViewModels之间的通信多么容易,如果你使用一个框架像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; 
    } 
} 

它应该是自我解释的。但是,如果您有任何问题,请告诉我,我会详细介绍。

1

通常这是通过使用消息传递完成的。

所有MVVM框架有一个消息总线,允许虚拟机间的通信,以便只是得到一个很好的框架和任务会得到如此简单(Simple MVVM Toolkit):

源VM:

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

接收VM:

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

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

感谢您的回答,但现在我试图远离外部框架。我不想在我的应用程序中添加另一个变量和问题的来源。任何其他选项? – ericpap

+1

如果您不想使用第三方MVVM框架,有几个选项。 1)实现你自己的Messenger类。 2)使用事件,并让虚拟机订阅彼此的事件。这就是说; MVVM不仅仅是一个实现INotifyPropertyChanged的类。这是一个由多个部分组成的设计模式,使者是其中的一部分。使用第三方框架比试图推出自己的产品更简单。 – BTownTKD

+0

嗨@BTownTKD,谢谢你的回答。我是所有这些技术的新手,我很难展现mvvm模式。 Rigth现在,我设法解决导航问题,并且在没有外部框架的情况下加载了多个视图,事实上,我没有看到引入新的sintaxis和我不真正需要的对象的观点。我尝试使用Caliburn.Micro,但似乎是“重新开始”来理解他的sintaxis。如果我不使用框架,还有什么我错过了?我会尝试使用事件并订阅viewModels。谢谢! – ericpap

相关问题