MVVM:松散耦合ViewModels

时间:2017-01-20 08:23:50

标签: wpf mvvm loose-coupling

我有班级,A,B,C,D

A引用了E和B以及C和D的列表。

在AViewModel中,它们在树中公开。

A的视图如图所示。

enter image description here

当显示选择对应视图的节点时。

E,B,C和D的ViewModel

我的问题如下:

例如,E是所选节点。我将它存储在AViewModel中作为"对象SelectedItem"。 以松散耦合的方式创建EViewModel的最佳方法是什么,这样我就不想在AViewModel中引用EViewModel。

更新

我在想一个解决方案,但我从未在其他地方看到过这个问题:

例如,我只能从AViewModel公开我的POCO(B,C,D,E)。在XAML中,我可以将ContentControl直接绑定到这些对象。使用转换器,当我绑定到B时,我可以拥有BViewModel等等。

2 个答案:

答案 0 :(得分:1)

在MVVM应用程序中以松散耦合的方式在视图模型和其他组件之间进行通信的一种常见且被广泛接受的方式是使用事件聚合器或信使。有关更多信息,请参阅以下链接。

使用事件聚合器模式在视图模型之间进行通信: https://blog.magnusmontin.net/2014/02/28/using-the-event-aggregator-pattern-to-communicate-between-view-models/

MVVM - MVVM中的Messenger和View Services: https://msdn.microsoft.com/en-us/magazine/jj694937.aspx

另一个选择是使用您注入视图模型的共享服务:https://social.msdn.microsoft.com/Forums/en-US/22907a0f-d805-4195-8272-7c284b72d2ee/example-of-using-shared-services-prism?forum=wpf

使用事件聚合器,信使或共享服务意味着您可以删除视图模型类之间的所有引用。

每个视图模型只知道一个事件聚合器/信使/共享服务,并且仅与此信息通信,而不是视图模型类来回相互之间具有强引用。视图模型A可以发送任何其他视图模型可以订阅以在内部监听和处理的任意数量的消息。

  

我的问题是关于在没有紧密耦合的情况下创建ViewModel实例的主题的最佳实践,而不是关于松散耦合的ViewModel之间的通信

创建另一个视图模型的实例而不创建字符串耦合是不可能的。如果一个视图模型创建另一个视图模型的实例,则根据定义它们是强耦合的。为了防止这种情况,您可以使用其他视图模型实现的接口类型注入视图模型,例如:

public ViewModelB(IViewModelA viewModelA)
{
    //...
}

然后ViewModelB依赖于接口类型而不是ViewModelA的具体实现。这比做这样的事情好一点,因为ViewModelA和ViewModelB总是 - 如上所述 - 彼此强烈耦合:

public ViewModelB()
{
    _viewModelA = new ViewModellA();
}

但是如果你真的关心视图模型类之间的松散耦合,你应该摆脱直接引用并开始使用事件聚合器或信使来在它们之间进行通信。

答案 1 :(得分:0)

如果您的A视图显示“列表”以及所选视图,则在AViewModel中使用EViewModel引用是完全可以接受的。 ViewModels可能是视图的“反射”。因此,如果A视图将包含EView,则AViewModel可能包含EViewModel。您只需嵌套视图模型,以便创建与视图层中相同的树。

最重要的是,我要做的不是在AViewModel中引用E或B,...而是仅引用EViewModel,BViewModel,......所以AView列表不显示模型类而是ViewModel类。您的SelectedItem被输入为ViewModel,您可以直接将“Display”视图部分绑定到SelectedItem。然后,您可以在视图图层上使用正确的DataTemplate来显示相应的视图。希望它有所帮助