2012-04-19 72 views
1

我有两个应用程序,一个是主应用程序,另一个是设计器表单应用程序。将ViewModel替换为另一个ViewModel

目前我有我的主要应用程序与棱镜和mef工作。我的主要应用程序中的一些视图只是数据输入表单。我想从我的设计器表单应用程序加载数据输入表单视图,以便可以编辑,但为此,我想使用不同的视图模型进行设计。我不希望表单附加到它通常的viewmodel并尝试获取数据等。

如何使用MEF我将能够提供不同的导出,以便它选择这个而不是通常的viewmodel?理想情况下,它只会替换主应用程序视图模型,所以它只是用它来代替。

这是我的例子来看,导入一个视图模型

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl 
{ 
    [ImportingConstructor] 
    public PatientDetailView(PatientDetailViewModel viewModel) 
    { 
     InitializeComponent(); 

     this.DataContext = viewModel; 
    } 
} 

这里是我的视图模型的基础:

[Export(typeof(PatientDetailViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    [ImportingConstructor] 
    public PatientDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IRegionManager regionManager) 
     : base(eventAggregator, dialogService, regionManager) 
    { 
     //Contains Commands etc for Saving Patient Detail Record 
     //Receiving patient detail etc 
    } 

}

UPDATE:

的以上包含在患者模块中部件。这适用于主应用程序。对于设计应用程序,我想的东西,如下面来代替上述视图模型:

[Export(typeof(PatientDetailViewModel))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    [ImportingConstructor] 
    public PatientDetailViewModel(IEventAggregator eventAggregator, IDialogService dialogService, IRegionManager regionManager) 
     : base(eventAggregator, dialogService, regionManager) 
    { 
     //Contains Commands etc for Designing the form 
     //No commands from the original VM so changes how it tries to work. 
    } 

}

以上工作来覆盖我的主要应用程序的默认行为。该VM将包含在Designer程序集或独立的designerVMs程序集中。

回答

0

因为这些是独立的应用程序,并且datacontext可以是任何对象,所以解决方案可以很简单。

视图被更改为按名称导入它的datacontext。

public static class MefContracts 
{ 
    public const string PatientDetailViewModel = "PatientDetailViewModel"; 
} 

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl, IPartImportsSatisfiedNotification 
{ 
    [Import(MefContracts.PatientDetailViewModel, typeof(object)] 
    private object vm; 

    public void OnImportsSatisfied() 
    { 
    this.DataContext = vm; 
    } 


    public PatientDetailView() 
    { 
    InitializeComponent(); 
    } 
} 

,如果真能那么这取决于你想要的应用程序只包括视图模型,并通过名称导出

[Export(MefContracts.PatientDetailViewModel, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

更新没有单独的组件(这是国际海事组织仍然是最好的选择,有在不同的程序集中使用vm是没有问题的),你可以使用简单的工厂来代替(取得ViewModel的方式):不用导入vm,而是导入一个可以创建vm的工厂。它创建的是一个配置值,必须在每个应用中设置不同的值。你将不得不用不同的契约导出vms,否则就没有(简单的)方式来区分它们。例如:

public static class MefContracts 
{ 
    public const string PatientDetailViewModelMain = "PatientDetailViewModelMain"; 
    public const string PatientDetailViewModelDesigner = "PatientDetailViewModelDesigner"; 
} 

//the main vm 
[Export(MefContracts.PatientDetailViewModelMain, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class PatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

//the other vm 
[Export(MefContracts.PatientDetailViewModelDesigner, typeof(object)))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class OtherPatientDetailViewModel : ViewModelBase, IRegionManagerAware 
{ 
    .... 
} 

[Export("PatientDetailView")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public partial class PatientDetailView : UserControl 
{ 
    [ImportingConstructor] 
    public PatientDetailView(PatientDetailViewModelFactory viewModelFactory) 
    { 
    InitializeComponent(); 
    this.DataContext = viewModelFactory.Create(); 
    } 
} 

[Export] 
class PatientDetailViewModelFactory 
{ 
    [Import] 
    private CompositionContainer container{ get; set; } 

    public enum AppType{ Main, Designer } 

    public AppType AppType{ get; set; } 

    public object Create() 
    { 
    return container.GetExportedValue<object>( 
     AppType == AppType.Main ? MefContracts.PatientDetailViewModelMain : 
           MefContracts.PatientDetailViewModelDesigner); 
    } 
} 
+0

好酷感谢回复。我的问题是我不知道我只包含我想要的ViewModel。由于主要应用程序虚拟机总是出口,当我包含我的视图的程序集。 我可以导出我的其他虚拟机在我的设计器应用程序,但然后有两个出口,我可以用我的新出口替换此导出? – 2012-04-19 10:41:08

+0

你不能把每个虚拟机放在一个单独的程序集中,并且每个应用程序只包含一个这样的程序集? – stijn 2012-04-19 12:44:52

+0

不是真的,ViewModel应该在同一个程序集中与View一起使用,从来没有在别处看过它们。它是该模块的一部分,对于设计人员而言,在不同的组件中看起来有点不对。我认为MEF是关于热交换组件的。 – 2012-04-19 14:27:12

0

尝试这样:

创建定义您的视图模型的接口:

public interface IPatientDetailViewModel{...} 

在您主要的应用从接口派生您的视图模型和修改导出属性。

[Export(typeof(IPatientDetailViewModel)] 
public class PatientDetailViewModel : ViewModelBase, 
    IRegionManagerAware, IPatientViewModel 
{ ... } 

我假设这些视图位于共享程序集中。添加一个默认的构造函数,以您的观点(如果不是在你的设计应用程序中使用MEF),并更改导入使用接口:

public PatientDetailView() 
{ 
    InitializeComponent(); 
} 

[ImportingConstructor] 
public PatientDetailView(IPatientDetailViewModel viewModel) 
{ 
    InitializeComponent(); 

    this.DataContext = viewModel; 
} 

现在,如果你的设计师的应用程序使用MEF可以导出不同的视图模型在视图的XAML中导入到使用MEF认为

[Export(typeof(IPatientDetailViewModel)] 
public class DesignPatientDetailViewModel : ViewModelBase, IPatientViewModel 
{ ... } 

,或者如果不使用

d:DataContext="{d:DesignInstance local:DesignPatientViewModel}" 

相关问题