2016-05-25 7 views
-1

現在、WPF/MVVMアプリケーションをNinjectからMEFに変換して、プラグインアーキテクチャを利用しています。プリズムも統一もなく、私はその道を下って行きたくありません。私はVS2015と.Net 4.6を使用しています。MEF:私のUserControlsでViewModelを作成する

MVVM Lightでよく使われていた手法を使用していましたが、ここではNinjectを使用してXAMLのViewModelをインスタンス化します。

public static ImageViewModel ImageVM => Kernel.Get<ImageViewModel>(); 

私はMEFに移りましたが、いくつかの選択肢があるかどうかを確認したいと思います。 Stack Exchangeの現在回答のある記事のほとんどはかなり古く、.NET 4.5が利用できるようになりました。


TL; DR

は、私が10件のUserControlが含まれているウィンドウを持っています。各ユーザーコントロールには、ViewModelの新しいインスタンスが添付されています。ウィンドウがxamlでユーザーコントロールを作成しているので、どのようにして各コントロールにViewModelの一意のインスタンスを取得できますか?私はInitializeComponentの後

CompositionInitializer.SatisfyImports(this); 

を追加すると見た

public partial class FingerprintControl{ 

    public FingerprintControl() { 
     InitializeComponent(); 
    } 

    [Import] 
    public FingerprintControlViewModel ViewModel 
    { 
     get { return DataContext as FingerprintControlViewModel; } 
     set { DataContext = value; } 
    } 

1つの提案()。しかし、これはSilverlightのみのクラスです。

私はhttps://www.nuget.org/packages/Microsoft.Composition/を見ましたが、MEF 2のドキュメンテーションはサイト上にはまったく存在しません。

また、ExportFactoryがMEF 2に追加されたことがわかりましたが、そのどちらかが役立つかどうかはわかりません。

私はMEF 2で静的メソッドCompositionContextExtensions.SatisfyImportsを見つけましたが、私はそれをどうすればいいのかわかりません。ドキュメントでは、「指定されたコンテキストから指定されたオブジェクトのインポートを満たしています。 (本物ではない便利な...)

+0

ユーザーコントロール用のビューモデルを作成していますか?ユーザーコントロールのUIロジックをカプセル化し、コードビハインドから削除しますか?もしそうなら、それをしないでください。データバインディングがどのようにコントロールで動作するのかを解明しています。それについて考える - TextBoxにはTextBoxViewModelがありますか?いいえ、その論理は制御しています。グリッドにはGridViewModelがありますか?いいえ。それと同じです。UserControlsは、必要なものをバインドするサーフェスにDependencyPropertiesを公開する必要があります。*または* DataContextに配置するものにバインドするように設計する必要があります。 (PersonEditorUserControlのPersonモデルなど) – Will

+0

私は自分のUserControlsに数多くのDependencyPropertiesを使用し、優れたMVVMパターンを持つように努力しています。この特定のケースでは、WindowのViewModelは完全に空であり、代わりに、各コントロールで非常にターゲットを絞ったViewModelをインスタンス化しました。ただ1つのViewModelを使用して、それぞれのウィンドウの注釈とボックスで10個の指紋を表示することは、非常に効率が悪く、SOLID原則に非常に反する。 –

答えて

1

我々はすべて我々のアプリのための静的メソッドとMEFのクラスラッパーを使用します。

public class Mef 
{ 
    private static CompositionContainer container = null; 
    public static CompositionContainer Container { get { return container; } } 

    private static AggregateCatalog catalog; 

    public static void Initialize() 
    { 
     catalog = new AggregateCatalog(); 
     catalog.Catalogs.Add(new DirectoryCatalog(path: ".", searchPattern: "*.exe")); 
     catalog.Catalogs.Add(new DirectoryCatalog(path: ".", searchPattern: "*.dll")); 
     container = new CompositionContainer(catalog); 
     StartWatch(); 
    } 

    private static void StartWatch() 
    { 
     var watcher = new FileSystemWatcher() { Path = ".", NotifyFilter = NotifyFilters.LastWrite }; 
     watcher.Changed += (s, e) => 
     { 
      string lName = e.Name.ToLower(); 
      if (lName.EndsWith(".dll") || lName.EndsWith(".exe")) 
       Refresh(); 
     }; 
     watcher.EnableRaisingEvents = true; 
    } 

    public static void Refresh() 
    { 
     foreach (DirectoryCatalog dCatalog in catalog.Catalogs) 
      dCatalog.Refresh(); 
    } 
} 

(注意:私たちは、動的にオンデマンドのプラグインをロードするために、上記を使用し、当社アプリケーションから別のカタログシステムを使用することができます - 複数のカタログシステムを使用したい場合があります)

次に、アプリのライフサイクルの早い段階で、通常はApp.Xamlコードビハインドコンストラクタでクラスを初期化します:

public App() 
    { 
     this.InitializeComponent(); 
     Mef.Initialize(); 
    } 

と私はクラス/コードビハインドコンストラクタ呼び出しでは、ベースレベルのMEF-インポートを持っている:

Mef.Container.SatisfyImports(this); 

・ホープ、このことができます。

+0

私は動的な更新は必要ありませんが、私はあなたがこの場合に行ったことが好きです。私は、私が必要としているようにSatisfyImports(これ))とはるかに良くなることをやっています!入力をありがとう、非常に感謝! –

関連する問題