Prism and MVVM Light Toolkit Usage

Topics: Prism v4 - Silverlight 4
Jun 3, 2011 at 12:33 PM
Edited Jun 3, 2011 at 12:37 PM

I have problems with regions in my SL4 project while breaking it into modules. I want to do that to enable

separate simultaneous development of different parts of application. Also this will be helpful in case there is

a need to target multiple platforms. I've never designed Composite Applications, but think this is a good

chance to try. So i've chosen Prism + MVVM Light Toolkit (like commands infrastructure that it provides,

also there are bunch of articles and videocasts about it) to implement that.

In Shell.xaml i have following markup (no CB):

 <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="280"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <!-- Ribbon -->
        <UserControl x:Name="Ribbon"
                Regions:RegionManager.RegionName="RibbonRegion"
                Grid.ColumnSpan="2" Margin="0,24,0,0"                
               />
        <!-- Diagram -->
        <UserControl Name="Diagram"
                Regions:RegionManager.RegionName="DiagramRegion"
                Grid.Row="1"
                Grid.Column="0"
                HorizontalAlignment="Left"                
                />
        <!-- Lower Grid -->
        <UserControl Name="DiagnosticsPanel"
            Regions:RegionManager.RegionName="DiagnosticsPanelRegion"
            Grid.Row="2"  
            Grid.Column="0"
              />
</Grid>

Also i have Unity Bootstrapper :

public class Bootstrapper : UnityBootstrapper 
    {
        protected override DependencyObject CreateShell()
        {
            var shell = ServiceLocator.Current.GetInstance<Shell>();
            return shell;
        }

        protected override void InitializeShell()
        {
            base.InitializeShell();
            Application.Current.RootVisual = Shell as UIElement;
            DispatcherHelper.Initialize();
        }

        protected override IModuleCatalog CreateModuleCatalog()
        {
            //base.CreateModuleCatalog();
            //var moduleCatalog = new ModuleCatalog();
            //moduleCatalog.AddModule(typeof (RibbonModule.RibbonModule));
            //return moduleCatalog;
            return new ModuleCatalog();
        }

        protected override void ConfigureModuleCatalog()
        {
            var ribbonModuleType = typeof(RibbonModule.RibbonModule);
            ModuleCatalog.AddModule(new ModuleInfo(ribbonModuleType.Name, ribbonModuleType.AssemblyQualifiedName));
        }

        public void Stop()
        {	    
            //ViewModelLocator.Cleanup();
        }        
    }

View (no CB) :

<UserControl x:Class="RibbonModule.RibbonView"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:ViewModel="clr-namespace:RibbonModule.ViewModel"
             mc:Ignorable="d"
             Height="300"
             Width="300"
            >

    <UserControl.Resources>
        <ViewModel:MainViewModel x:Key="mainViewModel" />
        <!--<ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Skins/MainSkin.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>-->
    </UserControl.Resources>

    <Grid x:Name="RibbonContainer" DataContext="{Binding Path=., Source={StaticResource mainViewModel}}">

        <TextBlock FontSize="36"
                   FontWeight="Bold"
                   Foreground="Purple"
                   Text="{Binding Welcome}"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   TextWrapping="Wrap" />

    </Grid>
</UserControl>

 

ViewModel :

 

public class MainViewModel : ViewModelBase
{
        public string Welcome
        {
            get
            {
                return "Welcome to MVVM Light";
            }
        }
}

 

RibbonModule.cs :

public class RibbonModule : IModule
    {
        private readonly IRegionManager _regionManager;
        private IUnityContainer _container;
        
        public RibbonModule(IRegionManager regionManager, IUnityContainer container)
        {
            _regionManager = regionManager;
            _container = container;
        }
        #region Implementation of IModule

        public void Initialize()
        {
            //_container.RegisterType<ISomeService, SomeService>();
            _regionManager.RegisterViewWithRegion("RibbonRegion", typeof (RibbonView));
        }

        #endregion

 

Project builds but at runtime I'm getting following error :

 

An exception occurred while trying to create region objects. 
    - The most likely causing exception was: 'System.Reflection.TargetInvocationException: 
Exception has been thrown by the target of an invocation. ---> 
Microsoft.Practices.Prism.Regions.Behaviors.RegionCreationException: An exception occurred while creating a region with name 'RibbonRegion'. 
The exception was: System.Collections.Generic.KeyNotFoundException: controlType
   at Microsoft.Practices.Prism.Regions.RegionAdapterMappings.GetMapping(Type controlType)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName).  
---> System.Collections.Generic.KeyNotFoundException: controlType
   at Microsoft.Practices.Prism.Regions.RegionAdapterMappings.GetMapping(Type controlType)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.CreateRegion(DependencyObject targetElement, String regionName)
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.TryCreateRegion()
   at Microsoft.Practices.Prism.Regions.Behaviors.DelayedRegionCreationBehavior.OnUpdatingRegions(Object sender, EventArgs e)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes 
methodAttributes, RuntimeType typeOwner)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, 
Boolean skipVisibilityChecks)
   at System.Delegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at Microsoft.Practices.Prism.Events.WeakDelegatesManager.Raise(Object[] args)
   at Microsoft.Practices.Prism.Regions.RegionManager.UpdateRegions()'.
    But also check the InnerExceptions for more detail or call .GetRootException().

 

It seems like my region binding is incorrect, but i did it according to guidlines, so maybe you can point where i missed something? Thanks in advance.

p.s. Test solution is here. I doubt someone will look, but just in case - http://db.tt/HVsihUT (100kb archive).

Developer
Jun 3, 2011 at 2:29 PM

Hi,

From the exception that you're experiencing, it looks like the problem is caused by the fact that there is no region adapter associated to the Ribbon control you're using in your region.

You could try overriding your Bootstrapper's ConfigureRegionAdapterMappings method to map the corresponding adapter for the ribbon control. You can read more about this in the following chapters from the Prism MSDN documentation:

Chapter 7: Composing the User Interface

Chapter 2: Initializing Prism Applications

I hope you find this helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi

Jun 7, 2011 at 2:56 PM
Edited Jun 7, 2011 at 3:01 PM

Tried to do that, but still had no luck running the application. Then changed region host type to ContentControl and everything worked.