2017-01-20 108 views
1

我有类,A,B,C,dMVVM:的ViewModels的松散耦合

A具有到E和B以及C和D

的列表在AViewModel这些露出的参考在树上。

A的视图看起来像图片中的样子。

enter image description here

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

没有为E,B,C和d

的ViewModels我的问题如下:

例如E是所选择的节点。我将它作为“object SelectedItem”存储在AViewModel中。 什么是以松散耦合方式创建EViewModel的最佳方式,以便我不想在AViewModel中引用EViewModel。

更新:

我在想一个解决方案,但我从来没有见过,在其他地方:

例如,我可以只露出我的波苏斯(B,C,d,e)从AViewModel。而在XAML中,我可以将ContentControl直接绑定到这些对象上。有了转换器,我可以有一个BViewModel,当我绑定到B等。

+0

能否请您发表您的XAML所以我们没有推倒重来? – lokusking

回答

0

如果您的A视图显示“列表”,再加上所选视图,那么在AViewModel中使用EViewModel引用是完全可以接受的。 ViewModels可能是观点的“反映”。因此,如果A视图将包含EView,则AViewModel可能包含EViewModel。您只需嵌套视图模型,以创建与视图图层中相同的树。最后,我要做的不是引用E或B,...在AViewModel中,而是仅引用EViewModel,BViewModel,...所以AView列表不显示模型类,但显示ViewModel类。您的SelectedItem被输入为ViewModel,您可以直接将“Display”视图部件绑定到SelectedItem。然后,您可以在视图图层上使用正确的DataTemplate来显示相应的视图。希望它有帮助

+0

这就是我目前正在做的:)但我总觉得这可以以更好的方式完成。 – jannagy02

1

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

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

MVVM - Messenger和查看服务在MVVM: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

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

代替具有来回彼此强引用视图模型类,每个视图模型只知道单个事件聚合器/信使/共享服务和只与这一个连通。视图模型A可以发送任何其他视图模型可以订阅的消息以在内部收听和处理。

我的问题是关于创建视图模型的实例话题的最佳做法,而无需紧密耦合,不是松耦合的ViewModels

,而无需创建创建另一个视图模型的实例之间的通信字符串耦合是不可能的。如果一个视图模型创建另一个视图模型的实例,则它们通过定义强烈耦合。为了防止这种情况,你可以用注射的接口类型,其他视图模型工具,例如:

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

然后ViewModelB依赖于一个接口类型,而不是一个具体的实现ViewModelA的视图模型。这是一个有点不是做这样的事情更好,因为再ViewModelA和ViewModelB永远是 - 如上所述 - 强耦合到对方:

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

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

+0

我的问题是关于创建视图模型的实例话题的最佳做法,而无需一个thigt耦合,不是松耦合的ViewModels之间的通信。 – jannagy02

+0

这是不可能的。如果一个视图模型创建另一个视图模型的实例,则它们通过定义强烈耦合。查看我编辑的答案以获取更多信息。 – mm8

+0

@ jannagy02使用工厂方法并返回(实例)接口。或者像棱镜一样使用DI容器 - 您请求一个类型(使用接口)并返回一个具体类型。但是,对于你指定什么这听起来像B,C,d和E都是波苏斯(这可能与自己的ViewModels包裹) - 这是确定的AViewModel了解他们,因为它的工作是塑造,改造和呈现数据风景。 – slugster