Prism Regions from Custom RegionAdapter Not Showing in RegionManager List

巧了我就是萌 提交于 2019-12-13 03:38:19

问题


I'm using Prism 6. I have a custom RegionAdapter for (AvalonDock) LayoutDocumentPane. I'm using it like this:

<!-- relevant lines from Shell.xaml. These regions are autoWired -->
<ad:LayoutDocumentPaneGroup>
    <ad:LayoutDocumentPane prism:RegionManager.RegionName="{x:Static inf:RegionNames.ContentRegion}">
    </ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
...
<ContentControl prism:RegionManager.RegionName={x:Static inf:RegionNames.TestRegion}">
...

My RegionAdapter:

public class AvalonDockLayoutDocumentRegionAdapter : RegionAdapterBase<LayoutDocumentPane>
{
    public AvalonDockLayoutDocumentRegionAdapter(IRegionBehaviorFactory factory) : base(factory)
    {
    }

    protected override void Adapt(IRegion region, LayoutDocumentPane regionTarget)
    {
        region.Views.CollectionChanged += (sender, e) =>
        {
            OnRegionViewsCollectionChanged(sender, e, region, regionTarget);
        };
    }

    private void OnRegionViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e, IRegion region, LayoutDocumentPane regionTarget)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            foreach (var item in e.NewItems)
            {
                var view = item as FrameworkElement;
                if (view != null)
                {
                    var layoutDocument = new LayoutDocument();
                    layoutDocument.Content = view;

                    var vm = view.DataContext as ILayoutPaneAware;
                    if (vm != null)
                    {
                        //todo bind to vm.Title instead
                        layoutDocument.Title = vm.Title;
                    }

                    regionTarget.Children.Add(layoutDocument);
                    layoutDocument.IsActive = true;
                }
            }
        } else if (e.Action == NotifyCollectionChangedAction.Remove)
        {
            foreach (var item in e.OldItems)
            {
                var frameworkElement = item as FrameworkElement;
                var childToRemove = frameworkElement.Parent as ILayoutElement;

                regionTarget.RemoveChild(childToRemove);
            }
        }
    }

    protected override IRegion CreateRegion()
    {
        return new Region();
    }
}

And of course I register it with the Bootstrapper

    ...
    protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
    {
        var mappings = base.ConfigureRegionAdapterMappings();

        mappings.RegisterMapping(typeof(LayoutDocumentPane), Container.Resolve<AvalonDockLayoutDocumentRegionAdapter>());

        return mappings;
    }

    protected override void InitializeShell()
    {
        var regionManager = RegionManager.GetRegionManager(Shell);
        // Here, regionManager.Regions only contains 1 Region - "TestRegion".
        // Where is my region from the custom RegionAdapter?

        Application.Current.MainWindow.Show();
    }

    protected override DependencyObject CreateShell()
    {
        return Container.Resolve<Shell>();
    }

    protected override void ConfigureModuleCatalog()
    {
        ModuleCatalog moduleCatalog = (ModuleCatalog)ModuleCatalog;
        moduleCatalog.AddModule(typeof(HelloWorldModule.HelloWorldModule));
    }
    ...

And my Module

...
    public HelloWorldModule(IRegionManager regionManager, IUnityContainer container)
    {
        _regionManager = regionManager;
        _container = container;
    }

    public void Initialize()
    {
        _container.RegisterTypeForNavigation<HelloWorldView>("HelloWorldView");

        // When uncommented, this next line works even though the region
        //  with this name doesn't appear in the list of regions in _regionManager
        //_regionManager.RegisterViewWithRegion(RegionNames.ContentRegion, typeof(HelloWorldView));
    }
...

Now, see that in the Bootstrapper.InitializeShell call, and the HelloWorldModule.Initialize call, I only have 1 region in the RegionManager - "TestRegion". If I registerViewWithRegion to my "ContentRegion" it puts an instance of the view in that region even though it's not listed in the Regions.

If I attempt to navigate from an ICommand function in my ShellViewModel (on a button click for instance) I can navigate to something in the TestRegion but not the ContentRegion. It seems I cannot navigate to any region created by my custom RegionAdapter. What am I missing?


回答1:


most probably your code below is causing you the issue.

protected override IRegion CreateRegion() { return new Region(); }

Try changing to return a region which can host multiple active views

protected override IRegion CreateRegion()
{
    return new AllActiveRegion();
}



回答2:


I saw this in your issue on GitHub.

Depending on how the control is created, you may have to set the Prism RegionManager on the control yourself via something like:

private readonly IRegionManager _regionManager;

public AvalonDockLayoutDocumentRegionAdapter( 
    IRegionBehaviorFactory regionBehaviorFactory, 
    IRegionManager regionManager 
    ) : base( regionBehaviorFactory ) {
    this._regionManager = regionManager;
}

protected override void Adapt( IRegion region, LayoutDocumentPane target ) {
    RegionManager.SetRegionManager( target, this._regionManager );
    // continue with Adapt
}


来源:https://stackoverflow.com/questions/33249284/prism-regions-from-custom-regionadapter-not-showing-in-regionmanager-list

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