【问题标题】:MVVM pass values between view modelsMVVM 在视图模型之间传递值
【发布时间】:2011-09-17 13:59:23
【问题描述】:

我尝试处理将值从一个 ViewModel 传递到另一个的问题。这是一个例子。

我们有父视图及其对应的 ViewModel,在该视图中我们选择项目,然后我们想要创建新的子视图(以编辑选择的详细信息),它在 XAML 中实例化其 ViewModel。 当我需要将值传递给 Child ViewModel 构造函数时会出现问题(它是必须从数据库中获取的数据的 Id)。我假设 Parent 的 ViewModel 必须与 Child 的 ViewModel 通信 - 但它无法完成,因为 Child 的 ViewModel 没有实例化,直到 Child 的 View 在 XAML 中执行此操作,所以我们不能使用 Messenger(MVVM Light Toolkit),而只是从 Parent 的 ModelView 传播该信息,因为 Child 的ModelView 无法订阅(注册该类型的消息)。

我不想破坏 MVVM 模式,也找不到任何好的解决方案。感谢您提供的所有帮助。

【问题讨论】:

  • 您使用的是视图模型定位器吗?您提到在子视图存在之前不会实例化您的虚拟机。你在后面的代码中设置数据上下文?我们的父虚拟机有一组子虚拟机。我们使用与 MVVM Light 非常相似的信使。
  • 哦,你不会“破坏” MVVM,它是指南而不是宗教。
  • 不,我不知道视图模型定位器 - 将检查出来。 Child 的 viewModel 的 DataContext 在 XAML 中设置。在我们的解决方案中,Parent 不能为 Child 收集 VM,它只能传递必须从 Child 的 VM 中的数据库中获取的数据的 Id。
  • 使用 ViewModel Locator,它就是你所需要的。在最简单的形式中,它是一个静态 MainViewModel,它在后面的 APP.XAML 代码中实例化。这样做将允许您使用 VS 中对象的属性正确绑定到您的元素。 MainViewModel 具有所有其他视图模型/模型集合。例如:Locator.Main.Parent.Child
  • Dan Andrews 感谢您的 cmets,我现在将检查该定位器。最好的问候

标签: silverlight mvvm


【解决方案1】:

MVVM 模式的主要租户之一是您应该能够在没有 View 的情况下执行 ViewModel 代码,以便对您的 View 逻辑进行单元测试。换句话说,理想情况下,您应该能够以“无头”模式执行您的应用程序。

在您的示例中,您声明 ParentView 创建了一个 ChildView ,该 ChildView 又创建了一个 ChildViewModel (您正在努力连接)。这可以在无头模式下工作吗?在我看来,您正在依靠您的视图来执行此父子导航。

如果你反过来,让 ParentViewModel 创建 ChildViewModel,你不再有 ViewModel 之间的通信问题。 ParentView 需要为正在创建的新 ChildViewModel 进行“监视”(即属性更改),并相应地构造 ChildView。

更详细的:

  1. ParentView 实例化 ParentVM
  2. 用户以需要孩子的方式进行交互
  3. ParentVM 创建一个 ChildVM,通过 ChildVM 属性公开它
  4. ParentView 处理生成的 PropertyChanged 事件,创建 ChildView,将其 DataContext 设置为 ChildVM。

【讨论】:

  • 无论我在哪里检查 MVVM 模式(在书中),VM 都会在 View 中实例化,例如资源。可能有什么我不明白的地方,请您纠正我吗?
  • 根据一种 MVVM 设计方法(在书中),VM 应该对其视图一无所知。那么如果不在 View 的 XAML / code behind 中,如何实例化 VM 呢?
  • @kkris1983 - 这是 MVVM 的“黄金法则”,VM 对视图一无所知。这样做意味着您无法在没有 View 的情况下运行 VM。这就是我要做的(1)ParentView 实例化 ParentVM,(2)用户以需要孩子的方式进行交互,(3)ParentVM 创建一个 ChildVM,通过 ChildVM 属性公开它,(4)ParentView 处理结果 PropertyChanged事件,创建一个 ChildView,将其 DataContext 设置为 ChildVM。那应该可以解决您的问题!它是 MVVM 的完全“有效”用法。
  • @ColinE 我不会那样做。应首先创建视图模型 IMO。最好将视图模型与视图完全分离,并使用某种发现机制为视图模型找到正确的视图。
  • 我更喜欢保持简单。问题来自正在与 MVVM 苦苦挣扎的人,我认为添加 IOC 或 DI 不会有太大帮助。我创建了许多 MVVM 应用程序,其中顶级视图创建了顶级视图模型,但仍然能够对视图模型进行单元测试并拥有设计时数据。让一些第三实体耦合视图和视图模型当然很好。但这不是必需的,它不是 MVVM 本身的一部分。
【解决方案2】:

如果您正在使用任何框架怎么办?我的意思是 MvvmLight、Caliburn Micro 或 Prism。每个框架都有一个消息传递基础设施。您可以利用它们使用发布/订阅方法来回传递状态。例如,看看棱镜。有几个快速入门展示了事件模型。您还可以维护一个视图控制器来协调视图之间的通信。

查看 Ward Bell 的 Prism Explorer 示例应用。这是 09 年的 article,但它今天仍然适用。尤其是看看他如何将实体对象从列表视图传递到子详细视图。

【讨论】:

  • 我使用 MvvmLight 并且我知道消息传递,但问题是父母的 VM 无法发送消息,因为孩子的 VM 可能尚未实例化,因此它无法注册该消息
  • 虽然我不熟悉w。在您的体系结构中,您可以有一个订阅事件的控制器,然后缓存结果。稍后在将其传递给状态缓存中的新视图时使用它来实例化视图。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-02
  • 1970-01-01
相关资源
最近更新 更多