Prism/MEF: how to create nested components with regions

Topics: Prism v4 - WPF 4
Dec 3, 2012 at 3:30 PM

Hello

I'm having the following problem.

I want to implement ribbon-based app with ribbon tabs as separate MEF component which can also contain MEF components - ribbon groups.

In my shell.xaml I have following code:

        <ribbon:Ribbon x:Name="Ribbon" cal:RegionManager.RegionName="AplicationRibbonControl"  >
            ........
        </ribbon:Ribbon>

For my Tab components I have following code in XAML:
<ribbon:RibbonTab x:Class="FI.VMRT.ObjectsTabUI"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             xmlns:cal="http://www.codeplex.com/prism"             
             xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
             x:Name="ObjectsTab"
             Header="Objects"
             cal:RegionManager.RegionName="ObjectsTabControl"
             >
</ribbon:RibbonTab>

And for my ribbon tab group component:
<ribbon:RibbonGroup x:Name="PlacementGroup" 
                    Header="Placement" 
                    x:Class="FI.VMRT.PlacementGroupUI"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
             xmlns:alp="clr-namespace:FI.Family.AkerLogoPack;assembly=AkerLogoPack"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
.... controls here .......
    </Grid>
</ribbon:RibbonGroup>

And while loading the application in my ribbon tab modude when I'm calling this:
_regionViewRegistry.RegisterViewWithRegion("AplicationRibbonControl", typeof(ObjectsTabUI));

I'm getting the following error:
An exception has occurred while trying to add a view to region 'AplicationRibbonControl'. 
    - The most likely causing exception was was: 'Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ObjectsTabUI, key "" ---> Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type ObjectsTabUI, key ""
   at Microsoft.Practices.Prism.MefExtensions.MefServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType)
   at Microsoft.Practices.Prism.Regions.RegionViewRegistry.CreateInstance(Type type)
   at Microsoft.Practices.Prism.Regions.RegionViewRegistry.<>c__DisplayClass1.<RegisterViewWithRegion>b__0()
   at Microsoft.Practices.Prism.Regions.Behaviors.AutoPopulateRegionBehavior.OnViewRegistered(Object sender, ViewRegisteredEventArgs e)'.
    But also check the InnerExceptions for more detail or call .GetRootException(). 

If I'm removing my ribbon tab group component, evertything works fine - I have an empty tab inserted into ribbon on my Shell window.
Can someone please give me a hint,  why this error occurs when I'm trying to add nested component?
Thank you!

Developer
Dec 3, 2012 at 8:21 PM

Hi,

Basically, when defining a control as a region, Prism needs to create a region and "adapt" it for the corresponding control. To do this, Prism has a collection of RegionAdapters registered. As out of the box, Prism provides the following RegionAdapters:

  • ContentControlRegionAdapter: Used to adapt a region to any control that inherits from the ContentControl class. 
  • ItemsControlRegionAdapter: Used to adapt a region to any control that inherits from the ItemsControl class.
  • SelectorRegionAdapter: Used to adapt a region to any control that inherits from the Selector class.

Based on my understanding, the cause of your problem is that you are defining a Ribbon control as a region, but Ribbon does not inherit from any of the aforementioned classes. Hence, as there is no RegionAdapter registered for Ribbons, Prism is not able to create the region.

Prism allows you to define and add your own custom RegionAdapters to add support for controls that are not supported by default (for example Ribbons). You can find more information about RegionAdapters and how to configure them in the following section of the Prism documentation:

Also, you might find the examples portrayed in the following thread useful in order to create a RegionAdapter for Ribbons:

Finally, if you want for Prism to provide a RibbonRegionAdapter as out of the box, you can vote in the following work item:

I hope you find this useful,

Damian Cherubini
http://blogs.southworks.net/dcherubini

Dec 4, 2012 at 8:42 AM

Hi Demian!

Thank you for your response! So if I get it right I need to create a region adapter for RibbonTab control - correct? I.e. by default Prism doesnt now how to insert items in rbbon - correct?

I'll try to use info on your links - thank you!