1

我有两个应用程序,一个是主应用程序,另一个是设计器表单应用程序。

目前,我的主要应用程序与 prism 和 mef 一起使用。我的主应用程序中的一些视图只是数据输入表单。我想要从我的设计器表单应用程序中加载一个数据输入表单视图,然后可以对其进行编辑,但要做到这一点,我想使用不同的视图模型进行设计。我不希望表单附加到它通常的视图模型并尝试获取数据等。

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

这是我的示例视图,导入视图模型

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

}

更新:

以上包含在患者模块组件中。这适用于主应用程序。对于 Designer 应用程序,我想将上面的视图模型替换为如下所示:

[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 程序集中。

4

2 回答 2

0

由于这些是单独的应用程序,并且数据上下文可以是任何对象,因此解决方案可以很简单。

视图更改为按名称导入其数据上下文。

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();
  }
}

然后根据应用程序,您只包含所需的 ViewModel 并按名称导出

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

如果您真的无法分离程序集(这仍然是 imo 最好的选择,将 vm 放在不同的程序集中没有任何问题),则更新,您可以使用一个简单的工厂来代替(以抽象获取 ViewModel 的方式):改为导入 vm,你导入一个可以创建 vm 的工厂。它创建哪一个取决于某些配置值,必须在每个应用程序中进行不同的设置。然后,您将不得不使用不同的合同导出 vm,否则没有(简单的)方法可以区分它们。例子:

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 );
  }
}
于 2012-04-19T10:05:13.630 回答
0

尝试这样的事情:

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

public interface IPatientDetailViewModel{...}

在您的主应用程序中,从界面派生您的视图模型并修改 Export 属性。

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

我假设视图位于共享程序集中。将默认构造函数添加到您的视图(如果在您的设计应用程序中不使用 Mef),并更改导入以使用接口:

public PatientDetailView()
{
    InitializeComponent();
}

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

    this.DataContext = viewModel;
}

现在,如果您的设计器应用程序使用 MEF,您可以导出不同的视图模型以导入到视图中

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

或者如果不使用 MEF,请使用

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

在您认为的 Xaml 中。

于 2012-04-19T19:23:41.453 回答