2012-04-26 104 views
0

我正在编写一个使用MEF和第三方库MEFedMVVM的WPF应用程序。使用MEFedMVVM在父视图/视图模型中实现视图模型优先方法

我试图创建一个设计,从而父视图模型有一个子视图模型的集合,我希望使用视图模型优先的方法,因为这保持视图模型以外的视图,从而保持代码更多视图以模型为中心,更多单元可测试。

我已阅读this discussionthis discussion关于使用DataTemplate进行视图以及Reed Copsy,Jr的建议here使用通用视图来查看模型映射资源。但是,我正在努力实现一些有效的工作。

我父母的看法是非常简单的:

[ExportViewModel("MyParentViewModel")] 
public class MyParentViewModel : ViewModelBase 
{ 
    [ImportingConstructor] 
    public MyParentViewModel() 
    { 
     var myChildVM = ServiceLocator.Current.GetInstance<MyChildViewModel>()); 
    } 
} 

这是孩子视图模型:

<UserControl x:Class="MyParentView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:meffed="clr-namespace:MEFedMVVM.ViewModelLocator;assembly=MEFedMVVM.WPF" 
      meffed:ViewModelLocator.ViewModel="MyParentViewModel" /> 

父视图模型从实现IContextAware基类型派生

[Export(typeof(MyChildViewModel))] 
[ExportViewModel("MyChildViewModel", true)] 
public class MyChildViewModel : ViewModelBase 
{ 
} 

而这有一个相应的视图:

<UserControl x:Class="MyChildView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:meffed="clr-namespace:MEFedMVVM.ViewModelLocator;assembly=MEFedMVVM.WPF" 
      meffed:ViewModelLocator.ViewModel="MyChildViewModel" /> 

起初,我还以为指定的ExportViewModel属性的第二个布尔参数MyChildViewModel将使用视图模型,第一种方法使一切工作为我的观点和看法车型在视图MEFed在一起'XAML代码。然而,事实证明这是不是这样的,什么我居然得到传递给IContextAware.InjectContext()当我在MyParentViewModel构造函数实例化一个MyChildViewModel对象是MyParentView对象。不是我期待和希望的对象。显然,我需要添加一些东西来将它们连接起来。任何人都可以提供一个如何做到这一点的例子吗?

谢谢!

+0

是有一个原因,你正在使用一个服务定位,让您的孩子VM?为什么不用MEF呢? – 2012-04-26 19:23:49

+0

为什么'MyChildView'指定'ViewModel =“MyParentViewModel”'? – 2012-04-26 19:25:19

+0

谢谢jberger,愚蠢的错字 - 已经纠正它。 – Neo 2012-04-30 08:45:10

回答

4

当你真的想用视图模型一,那么你应该做的:

[ExportViewModel("MyParentViewModel")] 
public class MyParentViewModel : ViewModelBase 
{ 
    // Create property for your child vm 
    public MyChildViewModel Child {get; private set} 

    // If you do MEF use constructor injection instead of servicelocator 
    [ImportingConstructor] 
    public MyParentViewModel(MyChildViewModel child) 
    { 
     this.Child = child; 
    } 
} 

然后定义一个DataTemplate您childvm

<DataTemplate DataType="{x:Type local:MyChildViewModel}"> 
    <view:MyChildViewUserControl /> 
</DataTemplate> 
在你的MainView你知道

要显示孩子的数据,否则你不需要孩子的财产;)所以简单地把一个ContentControl放在孩子数据应该去的地方并绑定到你的财产。

例如

<TabControl> 
    <TabItem Header="MyChildData"> 
     <ContentControl Content="{Binding Child}" /> 
    </TabItem> 
</TabControl> 

PS:代码写入没有IDE,所以错误的可能:)

+0

非常感谢,非常清楚。但是,在实现这一点之后,我现在认识到,在MEF与MEFedMVVM一起使用MEF时,视图模型优先方法可能是一个坏主意。我有效地规避了MEFedMVVM的内置导出/导入条款,它们连接了视图和视图模型,而是使用标准WPF内部结构通过DataType设置了DataTemplates。我认为这样做很好,因为它使视图不受视图模型影响,但如果设计允许,则可以使用视图优先方法并在视图模型中注入或实例化视图。 – Neo 2012-04-30 16:18:19