Prism 4 - locally scoped RegionManager

萝らか妹 提交于 2020-01-01 03:22:26

问题


I have silverlight 4 application with PRISM 4, I'm using MEF.

My Shell defines one main region in which modules are loaded, I want modules to have their own RegionManager, so regions that they define are places in local RegionManager instead of global. And I want this local RegionManager to be resolved by container (for type IRegionManager) when inside the module.

However the method from documentation:

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

Doesnt work for me, when resolving IRegionManager from inside child view I still get GlobalRegionManager.


回答1:


I was in the same situation as you, I had a nested region manager, but all of the child views were still getting the global region manager. I came up with what I consider a reasonable solution.

First I define an interface:

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

Then I setup a RegionBehavior like so:

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

Then apply this to all regions in your bootstrapper:

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

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

    return behaviours;
}

Then all you have to do is implement IRegionManagerAware on your view/viewmodel, probably like so:

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

Then when this view is added to a region, the behaviour will correctly set the RegionManager property to the currently scoped region manager.




回答2:


If you read the next line in the documentation it says "The Add method will return the new RegionManager that the view can retain for further access to the local scope."

so I would create a property in the view and pass the IRegionManger to it.

inside your view/viewModel.

public IRegionManager rm { get; set; }

then pass the IregionManager which was returned after adding the new view

view.rm = detailsRegionManager;

Hope that helps.



来源:https://stackoverflow.com/questions/6582612/prism-4-locally-scoped-regionmanager

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!