1

2 つのアプリケーションがあります。1 つはメイン アプリケーションで、もう 1 つはデザイナー フォーム アプリケーションです。

現時点では、主なアプリケーションでプリズムと 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
{
  ....
}

アセンブリを本当に分離できない場合は更新してください(これはまだ最良のオプションです。VMを別のアセンブリに配置しても問題はありません)、代わりに単純なファクトリを使用できます(ViewModelの取得方法を抽象化するため):代わりにVM をインポートするには、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 に答える