PRISM + SILVERLIGHT + NAVIGATION into MAINREGION

Topics: Prism v4 - Silverlight 4
Jun 19, 2013 at 11:01 AM
Hello everyone,
I started with Prism and I'm stuck for several days with a problem.
I have two modules, A and B. I want to navigate between these two modules on a single Mainregion by clicking on my menu.

Here is my TheBootstrapper class
public class TheBootstrapper : MefBootstrapper
    {
        protected override void InitializeShell()
        {
            base.InitializeShell();

            Application.Current.RootVisual = (UIElement)Shell;
        }

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

        protected override void ConfigureAggregateCatalog()
        {
            base.ConfigureAggregateCatalog();

            // Prism's AggregateCatalog is a catalog of all MEF composable parts
            // within the application.
            // We add the parts corresponding to the current assembly to it
            AggregateCatalog.Catalogs.Add(new AssemblyCatalog(this.GetType().Assembly));
        }

        protected override IModuleCatalog CreateModuleCatalog()
        {
            ModuleCatalog moduleCatalog = new ModuleCatalog();

            // this is the code responsible 
            // for adding Module1 to the application
            moduleCatalog.AddModule
            (
                new ModuleInfo
                {
                    // we make Module1 to be "OnDemand" module
                    // meaning it is not going to load at the app intialization
                    // time
                    InitializationMode = InitializationMode.OnDemand,
                    Ref = "ModuleA.xap",
                    ModuleName = "ModuleAImpl",
                    ModuleType = "ModuleA.ModuleAImpl, ModuleA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                }
            );
            moduleCatalog.AddModule
            (
                new ModuleInfo
                {
                    // we make Module1 to be "OnDemand" module
                    // meaning it is not going to load at the app intialization
                    // time
                    InitializationMode = InitializationMode.OnDemand,
                    Ref = "ModuleB.xap",
                    ModuleName = "ModuleBImpl",
                    ModuleType = "ModuleB.ModuleBImpl, ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                }
            );
            return moduleCatalog;
        }
    }
Shell.Xaml.cs
    public partial class Shell : UserControl
    {
        IModuleManager _moduleManager;
        [ImportingConstructor]
        public Shell([Import]IModuleManager moduleManager)
        {
            InitializeComponent();
            _moduleManager = moduleManager;
            _moduleManager.LoadModuleCompleted += _moduleManager_LoadModuleCompleted; 
        }
        void _moduleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
        {
            
        }

        private void Menu_ItemClick(object sender, Telerik.Windows.RadRoutedEventArgs e)
        {            
            switch ((e.OriginalSource as ExtendedMenuItem).AdditionalInfo.ToString())
            {
                case "ModuleB":
                    _moduleManager.LoadModule("ModuleBImpl");
                    break;
                case "ModuleA":
                    _moduleManager.LoadModule("ModuleAdministrationImpl");
                    break;
                default:
                    MessageBox.Show("Module indisponible");
                    break;
            }
        }
    }
AND ModuleA class (same thing for ModuleB)
[ModuleExport(typeof(ModuleAImpl))]
    public class ModuleAImpl : IModule
    {
        // import IRegionManager singlton from Prism
        [Import]
        public IRegionManager TheRegionManager { private get; set; }

        #region IModule Members

        public void Initialize()
        {
            var _region = TheRegionManager.Regions["Mainregion"];
            if (_region != null)
            {
                foreach (object view in _region.Views)
                {
                    _region.Remove(view);
                }
            }
            TheRegionManager.RegisterViewWithRegion("Mainregion", typeof(HostPageA));

        }

        #endregion
    }
My problem:
My problem is that I can not navigate between modules, I can display the ModuleA then ModuleB, but it's still frozen on ModuleB... How can I reactivate the module A or reload it.

Please, I need an easy solution Compatible with my code.

Thank you.
Jun 19, 2013 at 5:48 PM
Hi,

Based on my understanding, LoadModule method from your module manager loads the specified module and runs its Initialize method only if that module hadn't been loaded before, since the module manager keeps track of the modules already loaded (if you run the method twice, nothing will happen). Therefore, in order to solve your problem, you will need to verify if the module was loaded before to avoid calling the LoadModule method twice. The following code shows how your switch cases should look like for your modules:
...
case "ModuleB":
    if ( /*module not loaded*/ )
        _moduleManager.LoadModule("ModuleBImpl");
    else
        _regionManager.RequestNavigate("MainRegion", "HostPageB");
    break;
...

Hope this helps,

Federico Martinez
http://blogs.southworks.net/fmartinez
Jun 19, 2013 at 9:19 PM
Thank you very much for your answer. it's very clear. But how can I get the list of modules from my Shell?
Jun 24, 2013 at 5:56 PM
Hi,

Based on my understanding, you can retrieve the IModuleCatalog (from dependency injection or through service locator), which holds information about the modules that can be used by the application, and also exposes a Modules property which contains a collection of ModuleInfo with each of the modules information. In the ModuleInfo, you can check the State property to verify if that module was loaded or not.

Hope this helps,

Federico Martinez
http://blogs.southworks.net/fmartinez