Search code examples
wpfprismpanel

How can I use a Panel as a Region in Prism?


The prism documentation states that there are three region adapters available:

ContentControlRegionAdapter. This adapter adapts controls of type System.Windows.Controls.ContentControl and derived classes.

SelectorRegionAdapter. This adapter adapts controls derived from the class System.Windows.Controls.Primitives.Selector, such as the System.Windows.Controls.TabControl control.

ItemsControlRegionAdapter. This adapter adapts controls of type System.Windows.Controls.ItemsControl and derived classes.

Unfortunately, Panel does not fall into any of those categories, and I want to be able to write this in my .xaml.cs:

<Canvas cal:RegionManager.RegionName="{x:Static local:RegionNames.MainCanvas}">

How can we accomplish this?


Solution

  • The answer to this can be found in this very nice, descriptive blog post.

    However, I want the answer stored on StackOverflow as well :) It took a bit of searching to get this from Google. Here is my code that works with a basic Panel.

    Step 1 - create a new region adapter

    public class PanelHostRegionAdapter : RegionAdapterBase<Panel>
    {
        public PanelHostRegionAdapter(IRegionBehaviorFactory behaviorFactory)
            : base(behaviorFactory)
        {
        }
    
        protected override void Adapt(IRegion region, Panel regionTarget)
        {
            region.Views.CollectionChanged += (s, e) =>
                   {
                       if (e.Action == NotifyCollectionChangedAction.Add)
                       {
                           foreach (FrameworkElement element in e.NewItems)
                           {
                               regionTarget.Children.Add(element);
                           }
                       }
                       else if (e.Action == NotifyCollectionChangedAction.Remove)
                       {
                           foreach (FrameworkElement CurrentElement in e.OldItems)
                               regionTarget.Children.Remove(CurrentElement);
                       }
                   };
        }
    
        protected override IRegion CreateRegion()
        {
            return new AllActiveRegion();
        }
    }
    

    Step 2 - update your bootstrapper

    public class Bootstrapper : UnityBootstrapper
    {
        protected override DependencyObject CreateShell()
        {
           ...
        }
    
        protected override IModuleCatalog GetModuleCatalog()
        {
           ...
        }
    
        protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
        {
            RegionAdapterMappings Mappings = base.ConfigureRegionAdapterMappings();
            Mappings.RegisterMapping(typeof(Panel), Container.Resolve<PanelHostRegionAdapter>());
            return Mappings;
        }
    }