2011-04-20 134 views
7

我有两个ViewModels一个连接到主窗口,另一个连接到通过单击主窗口上的按钮打开的子窗口。子窗口包含项目列表,我想要选择一个项目并通过更新主窗口viewmodel将其显示在主窗口中。什么是完成这个最好的方法。谢谢!从另一个视图模型更新视图模型

+1

你特别要求“最好”的方式来做到这一点。什么定义“最好”给你?它可能意味着最快,最简单,最容易理解/调试,最少代码等。 – 2011-04-20 15:38:13

+0

最简单的是非常主观的,但我倾向于基于它的对象之间的真实关系的概念模型。如果他们是父母/孩子,直接引用可能非常简单。 – 2011-04-20 15:39:12

+1

在这种情况下,对我来说“最好”意味着最简单的方法,因为我对wpf和mvvm很陌生。 – codeBlue 2011-04-20 16:02:49

回答

10

有任何数量的方式来做到这一点。

  • 将对父视图模型的引用传递给子视图并让子视图调用主视图模型。

  • 让子视图模型触发父订阅的事件。

  • 使用messenger/mediator在两者之间进行通信。父母订阅,孩子发布消息。这提供了松耦合。

  • 将主视图模型设置为全局服务。以某种方式注册它。让孩子查找服务(需要全局服务是一个很常见的问题),然后在全局/通用界面上调用一些东西。

从我的经验来看,最简单的方法是#2。在子视图模型上定义一个事件。家长将不得不查看孩子(我不知道它是否包含它或您的视图模型的构建方式)并订阅该活动。

+0

任何这些方法都可能是合适的。这取决于上下文。除非虚拟机在紧密和概念上相关,否则耦合并不合适。 – 2011-04-20 15:30:52

+0

非常非常有用的答案,我的MainViewModel类开始看起来像一团糟。谢谢 – 2013-04-12 13:43:04

7

ViewModels之间进行通信的标准方式是使用某种类型的消息传递。一个很好的实施,这是MVVM Light Toolkit

下面是使用默认的信使一些(随机)从中代码:

//Registering: 
Messenger.Default.Register<IEnumerable<BookViewModel>>(this, true, fillSourceWith); 
Messenger.Default.Register<DisplayModeEnum>(this, ChangeMainTemplates); 
//with a specific "token" 
Messenger.Default.Register<object>(this, MessageTokens.ClearList, o => BookSource.Clear()); 

//Sending 
Messenger.Default.Send<List<BookViewModel>>(newBooks); 
Messenger.Default.Send<DisplayModeEnum>(DisplayModeEnum.MediumLayout); 
Messenger.Default.Send<object>(null, MessageTokens.ClearList); 
+0

-1。他在谈论父母/孩子的关系。消息在这里不是个好主意。 – Euphoric 2011-04-20 15:31:22

+2

我认为这里的消息应该没问题。没有消息,你不得不以某种方式将你的视图模型结合起来。 – 2011-04-20 15:33:52

+0

消息可能适用,也可能不适用。这个问题可能太复杂了,但这是一个很好的解决方案。 – 2011-04-20 15:34:38

1

最好的办法是从孩子到父母进行某种引用,并在关闭孩子时更新父母。

或者您可以在孩子身上发生某种事件并让家长听这个事件。然后,当孩子关门时,你提出这个事件。

如果两个ViewModel都是逻辑无关的,则使用消息传递。

[咆哮]不要人们甚至知道面向对象的基本原理或什么? [/咆哮]

+1

我不认为在这种情况下使用信使是不好的设计。这取决于任何数量的因素,但发送简单的消息可能比在两个虚拟机之间建立面向对象的关系要简单得多并且更有效 – 2011-04-20 15:50:54

+0

我认为问题在于没有最佳实践方法来做到这一点作为MVVM模式的一部分。 – Will 2011-04-20 15:51:26

1

我几天有同样的问题;-)

前最后我用了一个调解员进行沟通都视图模型。事实上,我使用MVVM Light的Messenger。

public void Search(object parameter) 
     { 
      ChildWindow window = new ChildWindow(); 

      SearchWindow pageSearch = new SearchWindow(); 

      window.Content = pageSearch; 
      window.Show(); 

      Messenger.Default.Register<Messages.CloseWindowMessage>(this, action => this.closeWindow(action)); 
     } 

之后,我定义的一切,我需要从主窗口知道消息:

public class CloseWindowMessage : MessageBase 
    { 
     public bool Result { get; set; } 
     public Model.Selected Selected { get; set; } 
    } 

最后的消息来自childwindow回你只需要注册结果的消息和对象,你想要回来。

您应该从视图的代码隐藏中注册以关闭窗口。

-1

我认为在两种视图模型之间传递消息的最佳方式是事件编程。