2011-07-05 2 views
5

프리즘 4와 함께 실버 라이트 4 응용 프로그램이 있습니다. MEF를 사용하고 있습니다.프리즘 4 - 로컬 스코프 RegionManager

셸은 모듈이로드되는 하나의 주 영역을 정의합니다. 모듈에 고유 한 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); 

나던 작품은, 나는 아직도 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 : 다음

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

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

    return behaviours; 
} 

:

/// <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; 
    } 
} 

이 그런 다음 부트 스트 래퍼의 모든 지역이 적용

먼저 나는 인터페이스를 정의 아마도 다음과 같이 view/viewmodel에 IRegionManagerAware을 구현하면됩니다. 이보기는 지역에 추가 될 때

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

그런 행동은 올바르게 현재 범위의 지역 매니저로 RegionManager 속성을 설정합니다.

+1

아주 좋습니다. 나는 여전히 PRISM을 사용하고 있지만 거의 완전히 재 작성되었습니다. 프리즘은 훌륭한 확장 가능한 아키텍처를 가지고 있습니다. –

+1

훌륭한 작품입니다. 계약 만 사용 중지했습니다. – lvmeijer

2

문서의 다음 줄을 읽으면 "Add 메서드는 뷰가 로컬 범위에 대한 추가 액세스를 위해 보유 할 수있는 새 RegionManager를 반환합니다."

그래서보기에서 속성을 만들고 IRegionManger를 전달합니다.

내 view/viewModel 내에 있습니다.

public IRegionManager rm { get; set; } 

는 새보기 도움이

view.rm = detailsRegionManager; 

희망을 추가 한 후 반환 된 IregionManager를 전달합니다.

+2

실제로 저는 IoC로 intergarte하고 RegionManager를 적절히 해결할 것을 기대했지만 사용자가 직접 관리해야하는 것처럼 보입니다. –

+0

@AlexBurtsev 최근의 답변을 살펴보십시오. 수동으로 배선하는 솔루션을 찾은 것 같습니다. – Lukazoid