使用MEFedMVVM在父视图/视图模型中实现视图模型优先方法

时间:2012-04-26 08:57:32

标签: wpf mef datatemplate mefedmvvm

我正在使用MEF和名为MEFedMVVM的第三方库编写WPF应用程序。

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

我已阅读this discussionthis discussion关于在视图中使用DataTemplate,以及Reed Copsy,Jr的建议here使用通用视图查看模型映射资源。但是,我正在努力实际实现有用的东西。

我的父视图非常简单:

<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 的基本类型:

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

这是子视图模型:

[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" />

最初,我认为在 MyChildViewModel ExportViewModel 属性上指定第二个布尔参数会使所有内容都使用视图模型优先方法作为我的视图和视图模型在视图的XAML代码中一起使用MEFed。但事实证明情况并非如此,当我在 MyParentViewModel中实例化 MyChildViewModel 对象时,我实际上将其传递给 IContextAware.InjectContext() / em> constructor是一个 MyParentView 对象。不是我期待和希望的 MyChildView 对象。显然,我需要添加一些东西来连接它们。有人可以提供一个如何做到这一点的例子吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

当你真的想先使用view-model-then时,你应该这样做:

[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;
    }
 }

然后为您的childvm定义一个datatemplate

 <DataTemplate DataType="{x:Type local:MyChildViewModel}">
     <view:MyChildViewUserControl />
 </DataTemplate>

在您的MainView中,您知道要显示子数据的位置,否则您不需要子属性;)所以只需将ContentControl放在子数据应该去的地方并绑定到您的属性。

e.g。

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

PS:代码是在没有IDE的情况下编写的,因此可能出错:)