2011-07-05 16 views
5

私はPRISM 4で銀色4アプリケーションを使用しています。私はMEFを使用しています。プリズム4 - ローカルスコープリージョンマネージャ

My Shellは、モジュールがロードされる1つのメインリージョンを定義します。モジュールには独自のRegionManagerがあるため、定義するリージョンはグローバルではなくローカルのRegionManagerに配置されます。そして、モジュール内にあるときに、このローカルのRegionManagerをコンテナ(IRegionManager型用)で解決する必要があります。

しかしドキュメントからの方法:子ビュー内からIRegionManagerを解決するときに

IRegion detailsRegion = this.regionManager.Regions["DetailsRegion"]; 
View view = new View(); 
bool createRegionManagerScope = true; 
IRegionManager detailsRegionManager = detailsRegion.Add(view, null, 
          createRegionManagerScope); 

私のためにdoesntの仕事は、私はまだGlobalRegionManagerを取得します。

答えて

10

私はあなたと同じ状況にありましたが、ネストされたリージョンマネージャーがありましたが、すべての子ビューはまだグローバルリージョンマネージャーを取得していました。私は合理的な解決策と考えたものを考え出した。

まず、私はインターフェイスを定義します。

/// <summary> 
/// An interface which is aware of the current region manager. 
/// </summary> 
public interface IRegionManagerAware 
{ 
    /// <summary> 
    /// Gets or sets the current region manager. 
    /// </summary> 
    /// <value> 
    /// The current region manager. 
    /// </value> 
    IRegionManager RegionManager { get; set; } 
} 

その後、私はセットアップそうのようなRegionBehavior

/// <summary> 
/// A behaviour class which attaches the current scoped <see cref="IRegionManager"/> to views and their data contexts. 
/// </summary> 
public class RegionAwareBehaviour : RegionBehavior 
{ 
    /// <summary> 
    /// The key to identify this behaviour. 
    /// </summary> 
    public const string RegionAwareBehaviourKey = "RegionAwareBehaviour"; 

    /// <summary> 
    /// Override this method to perform the logic after the behaviour has been attached. 
    /// </summary> 
    protected override void OnAttach() 
    { 
     Region.Views.CollectionChanged += RegionViewsChanged; 
    } 

    private void RegionViewsChanged(object sender, NotifyCollectionChangedEventArgs e) 
    { 
     Contract.Requires<ArgumentNullException>(e != null); 

     if (e.NewItems != null) 
      foreach (var item in e.NewItems) 
       MakeViewAware(item); 
    } 

    private void MakeViewAware(object view) 
    { 
     Contract.Requires<ArgumentNullException>(view != null); 

     var frameworkElement = view as FrameworkElement; 
     if (frameworkElement != null) 
      MakeDataContextAware(frameworkElement); 

     MakeAware(view); 
    } 

    private void MakeDataContextAware(FrameworkElement frameworkElement) 
    { 
     Contract.Requires<ArgumentNullException>(frameworkElement != null); 

     if (frameworkElement.DataContext != null) 
      MakeAware(frameworkElement.DataContext); 
    } 

    private void MakeAware(object target) 
    { 
     Contract.Requires<ArgumentNullException>(target != null); 

     var scope = target as IRegionManagerAware; 
     if (scope != null) 
      scope.RegionManager = Region.RegionManager; 
    } 
} 

その後、あなたのブートストラップ内のすべての地域にこれを適用します。

protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors() 
{ 
    var behaviours = base.ConfigureDefaultRegionBehaviors(); 

    behaviours.AddIfMissing(RegionAwareBehaviour.RegionAwareBehaviourKey, typeof(RegionAwareBehaviour)); 

    return behaviours; 
} 

その後あなたのビュー/ viewmodelにIRegionManagerAwareを実装するだけです。おそらくそうです:このビューは、領域に追加されたときに

public class MyView : IRegionManagerAware 
{ 
    IRegionManager RegionManager { set; get; } 
} 

その後、動作が正しく、現在スコープ領域マネージャにRegionManagerプロパティを設定します。

+1

非常に良い。私はまだPRISMを使用していますが、ほとんど完全に書き換えられました。プリズムは素晴らしい拡張可能なアーキテクチャを持っています。 –

+1

素晴らしい作品です。私は契約を無効にしました – lvmeijer

2

ドキュメントの次の行を読むと、 "Addメソッドは、ビューがローカルスコープへのさらなるアクセスのために保持できる新しいRegionManagerを返します。"

私はビューでプロパティを作成し、それにIRegionMangerを渡します。

あなたのビュー/ viewModel内。

public IRegionManager rm { get; set; } 

はその後

view.rm = detailsRegionManager; 

新しいビューを追加した後に役立ちます希望を返されたIregionManagerを渡します。

+2

確かに、IoCにintergarteしてRegionManagerを適切に解決することを期待しましたが、自分で管理する必要があるようです。 –

+0

@AlexBurtsev私の最近の答えを見てみると、私はそれを手作業で配線する解決策を見つけたと思う。 – Lukazoid

関連する問題