【问题标题】:Implementing a view-model-first approach inside a parent view/view model using MEFedMVVM使用 MEFedMVVM 在父视图/视图模型中实现视图模型优先的方法
【发布时间】:2012-04-26 08:57:32
【问题描述】:

我正在使用 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" />

最初,我认为在 MyChildViewModelExportViewModel 属性上指定第二个布尔参数将使所有工作都使用视图模型优先的方法作为我的视图和视图模型在视图的 XAML 代码中一起使用 MEF。然而,事实并非如此,当我在 MyParentViewModel 构造函数是一个 MyParentView 对象。不是我期待和希望的 MyChildView 对象。显然,我需要添加一些东西来将它们连接在一起。谁能提供一个如何做到这一点的例子?

谢谢!

【问题讨论】:

  • 您使用 ServiceLocator 获取子 VM 是否有原因?为什么不加入 MEF?
  • 为什么MyChildView 指定ViewModel="MyParentViewModel"
  • 感谢 jberger,愚蠢的错字 - 已更正。
  • 您的MyParentView.xaml.csMyChildView.xaml.cs 文件是什么样的?
  • 除了默认构造函数中的 InitializeComponent() 调用之外为空。

标签: wpf mef datatemplate mefedmvvm


【解决方案1】:

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

[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 DataType="{x:Type local:MyChildViewModel}">
     <view:MyChildViewUserControl />
 </DataTemplate>

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

例如

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

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

【讨论】:

  • 谢谢你,这很清楚。但是,在实现了这一点后,我现在意识到在将 MEF 与 MEFedMVVM 一起使用时,视图模型优先的方法可能不是一个好主意。我有效地规避了 MEFedMVVM 的内置导出/导入规定,这些规定将视图和视图模型连接起来,而是使用标准的 WPF 内部通过带有 DataType 集的 DataTemplates 连接它们。我认为这很好,因为它将视图排除在视图模型之外,但是如果设计允许,使用视图优先的方法并在视图模型中注入或实例化视图是可以接受的。
猜你喜欢
  • 1970-01-01
  • 2013-01-04
  • 1970-01-01
  • 2017-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多