2013-03-08 4 views
6

私はすでにいくつかのチュートリアルを検索しており、複数形のPRISMの紹介も見ています。しかし、ほとんどの例は、単一のコンテナを使用し、いくつかのMefコンテナでこの機能を実装する方法に関する情報が不足していることに基づいています。 私の単純なhelloworldモジュールはweb tutorialに基づいています。私のコードはHelloModuleだけで止まっていて、チュートリアルのようにUnityではなくMefを使用している点を除いて同じです。PRISMとMEFを使用してUIにビューを注入する方法は?

私のビューモデルで私のビューを初期化する方法。私は実験を通じて発見した唯一の作業の方法は、ビューのコンストラクタにビューモデルを初期化することである。

HelloView.xaml.cs 
namespace Hello.View 
{ 
    [Export] 
    public partial class HelloView : UserControl, IHelloView 
    { 
     public HelloView() 
     { 
      InitializeComponent(); 
      Model = new HelloViewModel(this); 
     } 

     public IHelloViewModel Model 
     { 
      //get { return DataContext as IHelloViewModel; } 
      get { return (IHelloViewModel)DataContext; } 
      set { DataContext = value; } 
     } 
    } 
} 

そして標準モジュールの初期化コード:

[ModuleExport(typeof(HelloModule), InitializationMode=InitializationMode.WhenAvailable)] 
    public class HelloModule : IModule 
    { 
     IRegionManager _regionManager; 

     [ImportingConstructor] 
     public HelloModule(IRegionManager regionManager) 
     { 
      _regionManager = regionManager; 
     } 

     public void Initialize() 
     { 
      _regionManager.Regions[RegionNames.ContentRegion].Add(ServiceLocator.Current.GetInstance<HelloView>()); 
     } 
    } 

しかし、誰かがどのようにこれに対する正しい方法を伝えることができますもの、私はこれをモジュールの初期化のセクションで行う必要があります。

+0

は、ビューのコンストラクタでのビュー・モデルは良い方法です初期化します。あなたはどんな問題をそれのようにしていますか? – thumbmunkeys

+0

Unityでは、コンテナを介してビューモデルを初期化します。それは私にmefで同等の方法を検索させますか?しかし、もしあなたがそれを良い方法と言えば、私は多くのことを固くはしません。 – user2147528

答えて

1

あなたがHelloViewを実装する方法がViewは、いくつかのシナリオで結構ですIHelloViewModelの正確な実装を知っている必要があることを意味していますが、このinterfaceを必要としないということを意味します。

私が提供する例では、私はproperty injectionを使用していますが、constructor injectionも良いでしょう。あなたがinterfaceを使用したい場合は

あなたはこのようにそれを実装することができます。それ以外の場合は

[Export(typeof(IHelloView)] 
public partial class HelloView : UserControl, IHelloView 
{ 
    public HelloView() 
    { 
     InitializeComponent(); 
    } 

    [Import] 
    public IHelloViewModel Model 
    { 
     get { return DataContext as IHelloViewModel; } 
     set { DataContext = value; } 
    } 
} 

[Export(typeof(IHelloViewModel))] 
public class HelloViewModel : IHelloViewModel 
{ 
} 

それは次のようになります。

[Export(typeof(IHelloView)] 
public partial class HelloView : UserControl, IHelloView 
{ 
    public HelloView() 
    { 
     InitializeComponent(); 
    } 

    [Import] 
    public HelloViewModel Model 
    { 
     get { return DataContext as HelloViewModel; } 
     set { DataContext = value; } 
    } 
} 

[Export] 
public class HelloViewModel 
{ 
} 

もう一つ:あなたはしたくない場合Viewsを変更するか、それらの実装をいくつか提供する場合は、interfaceは必要ありません。

11

MatthiasGは、MEFでモジュールを定義する方法を示しています。ビュー自体はIModuleを実装していないことに注意してください。しかし、PRISMでMEFを使用することの興味深い部分は、起動時にモジュールをUIにインポートする方法です。

ここでは、原則としてシステムを説明することができますが、正しい方向に向けるかもしれません。そこすべてに多くのアプローチは常にありますが、これは私がベストプラクティスとどのような私は非常に良い経験をしたと理解するものである:

プリズムとUnityと同様に

ブートストラップ

、それがすべてで始まりますブートストラップはMefBootstrapperに由来し、Microsoft.Practices.Prism.MefExtensionsに由来します。ブートストラップはMEFコンテナを設定し、サービス、ビュー、ViewModel、モデルなどのすべてのタイプをインポートします。

エクスポートビュー(モジュール)

これはMatthiasGが参照している部分です。モデルは[Export(typeof(MyModel)]属性を使用して、(MatthiasGを参照してください、あまりにもインターフェースすることができます)その具体的なタイプとしての地位をエクスポート

  • :私の練習は、GUIモジュールに次のような構造です。 [PartCreationPolicy(CreationPolicy.Shared)]とマークすると、インスタンスが1つしか作成されないことを示します(シングルトン動作)。

  • ビューモデルは単にモデルのように、その具体的なタイプとして自身をエクスポートし、コンストラクタ注射モデルをインポート:

    [ImportingConstructor] パブリッククラスMyViewModel(mymodelというモデル) { _model =モデル。 }

  • Viewはコンストラクタ・インジェクション経由のViewModelをインポートし、同じ方法でのViewModelはモデル

  • をインポートそして今、これは重要です:由来し、特定の属性を持つビューの輸出そのものを'standard' [Export]属性。次に例を示します。

[ViewExport(RegionName = RegionNames.DataStorageRegion)] 
public partial class DataStorageView 
{ 
    [ImportingConstructor] 
    public DataStorageView(DataStorageViewModel viewModel) 
    { 
     InitializeComponent(); 
     DataContext = viewModel; 
    } 
} 

[ViewExport]属性

[ViewExport]属性には2つのことを行います。それは[Export]属性から派生しているので、それはビューをインポートするMEFコンテナに指示します。何ですか?これは、それのdefintionに隠されている:コンストラクタのシグネチャは次のようになります。

public ViewExportAttribute() : base(typeof(UserControl)) {} 

UserControlの種類と[Export]のコンストラクタを呼び出すことで、すべてのビューは、MEFコンテナ内UserControlとして登録されます。

第2に、ビューをプラグインするシェルUIの領域を決定するために後で使用されるプロパティRegionNameを定義します。 RegionNameプロパティは、インターフェイスIViewRegionRegistrationの唯一のメンバです。属性クラス:AutoPopulateExportedViews行動:ビュー

をインポート

/// <summary> 
/// Marks a UserControl for exporting it to a region with a specified name 
/// </summary> 
[Export(typeof(IViewRegionRegistration))] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
[MetadataAttribute] 
public sealed class ViewExportAttribute : ExportAttribute, IViewRegionRegistration 
{ 
    public ViewExportAttribute() : base(typeof(UserControl)) {} 

    /// <summary> 
    /// Name of the region to export the View to 
    /// </summary> 
    public string RegionName { get; set; } 
} 

は今、システムの最後の重要な部分はあなたのシェルの部分に取り付け行動、です。これは、この行とMEFコンテナから、あなたのモジュールのすべてをインポート:彼らはIViewRegionRegistrationを実装するメタデータ属性を、持っている場合

[ImportMany] 
private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews; 

これは、コンテナからUserControlとして登録されているすべての種類をインポートします。 [ViewExport]属性が実行するため、[ViewExport(...)]とマークされたすべてのタイプをインポートすることを意味します。

/// <summary> 
/// A behavior to add Views to specified regions, if the View has been exported (MEF) and provides metadata 
/// of the type IViewRegionRegistration. 
/// </summary> 
[Export(typeof(AutoPopulateExportedViewsBehavior))] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class AutoPopulateExportedViewsBehavior : RegionBehavior, IPartImportsSatisfiedNotification 
{ 
    protected override void OnAttach() 
    { 
     AddRegisteredViews(); 
    } 

    public void OnImportsSatisfied() 
    { 
     AddRegisteredViews(); 
    } 

    /// <summary> 
    /// Add View to region if requirements are met 
    /// </summary> 
    private void AddRegisteredViews() 
    { 
     if (Region == null) return; 

     foreach (var view in _registeredViews 
      .Where(v => v.Metadata.RegionName == Region.Name) 
      .Select(v => v.Value) 
      .Where(v => !Region.Views.Contains(v))) 
      Region.Add(view); 

    } 

    [ImportMany()] 
    private Lazy<UserControl, IViewRegionRegistration>[] _registeredViews; 
} 

お知らせ.Where(v => v.Metadata.RegionName == Region.Name)

最後のステップは、それがOnAttach()プロパティの中bahviorがない領域にビューをプラグインすることです。これは、属性のRegionNameプロパティを使用して、特定のリージョンに対してエクスポートされたビューのみを取得し、ビヘイビアをアタッチしています。

動作がブートストラップであなたのシェルの地域に添付されます:私たちは完全な円を来ている

protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors() 
{ 
    ViewModelInjectionBehavior.RegionsToAttachTo.Add(RegionNames.ElementViewRegion); 

    var behaviorFactory = base.ConfigureDefaultRegionBehaviors(); 
    behaviorFactory.AddIfMissing("AutoPopulateExportedViewsBehavior", typeof(AutoPopulateExportedViewsBehavior)); 
} 

、私は願って、これはあなたに物事がMEFと場所に分類方法のアイデアを取得し、プリズム。

そして、あなたはまだ退屈いないのであれば:これは完璧です:

Mike Taulty's screencast

+0

こんにちはマーク、素晴らしい書き込み。私はMEFとPRISMを使い始めようとしています。正直言って私は完全に失われています。私はすべての基本的なチュートリアルを見つけることができません。MSDNのものは、ビットとピースだけをカバーしています。サンプルプロジェクトは、私が見ていることを知らずに私にとってはあまりにも複雑です。 MEFとPRISMに関する良いチュートリアルを知っていますか? – NZJames

+0

@ user1122909彼女にはあなたが好きです。 Mike TaultyのScreencast(私の記事のリンク)を見ましたか?数時間であなたは本当にたくさんのことを学ぶでしょう。私は基本的にPRISM/MEFをこれらのビデオと他のもので学びました。 PRISMのマニュアルも参照することができますが、私はここであまりにも高い期待を持っていないでしょう... – Marc

+0

いいえ、今見て、行くだろう、ありがとう。 MEF/Prismという質問に私は考えていません。 http://stackoverflow.com/questions/19526287/wpf-mef-prism-initial-region-loading – NZJames

関連する問題