Prism 4 - локально управляемый RegionManager - PullRequest
5 голосов
/ 05 июля 2011

У меня есть приложение silverlight 4 с PRISM 4, я использую MEF.

Моя оболочка определяет один основной регион, в который загружаются модули. Я хочу, чтобы модули имели собственный RegionManager, поэтому определяемые ими регионы размещаются в локальном RegionManager, а не в глобальном. И я хочу, чтобы этот локальный RegionManager был разрешен контейнером (для типа IRegionManager) внутри модуля.

Однако метод из документации:

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

У меня не работает, при разрешении IRegionManager из дочернего представления я все еще получаю GlobalRegionManager.

Ответы [ 2 ]

10 голосов
/ 10 февраля 2012

Я был в той же ситуации, что и вы, у меня был вложенный менеджер региона, но все дочерние представления все еще получали глобального менеджера региона. Я пришел к тому, что считаю разумным решением.

Сначала я определю интерфейс:

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

Тогда все, что вам нужно сделать, это реализовать IRegionManagerAware в вашем представлении / модели представления, вероятно, так:

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

Затем, когда это представление добавляется в регион, поведение правильно установит свойство RegionManager для текущего менеджера области в области.

2 голосов
/ 05 июля 2011

Если вы прочитаете следующую строку в документации, там написано: «Метод Add вернет новый RegionManager, который представление может сохранить для дальнейшего доступа к локальной области.»

, поэтому я бы создал свойство впредставление и передайте ему IRegionManger.

внутри вашего view / viewModel.

public IRegionManager rm { get; set; }

, затем передайте IregionManager, который был возвращен после добавления нового представления

view.rm = detailsRegionManager;

Надеюсь, это поможет.

...