StepUp
StepUp

Reputation: 38094

How to load a module and navigate to the module? Prism

I have two modules: ModuleLogging and ModuleItems. My Shell has declaration:

<Grid>
   <DockPanel LastChildFill="True">
    <ContentControl  DockPanel.Dock="Top" prism:RegionManager.RegionName="{x:Static inf:RegionNames.TheUpperRegion}" Margin="5" />
    <ContentControl prism:RegionManager.RegionName="{x:Static inf:RegionNames.TheBottomRegion}" Margin="5"/>                     
   </DockPanel>

    <ContentControl prism:RegionManager.RegionName="{x:Static inf:RegionNames.TheWholeRegion}" Margin="5"  />
</Grid>

The ModuleLogging is loaded at first. Then if user is authenticated, I would like to load ModuleItems. As I understood correctly, I should instantiate

My bootstrapper class:

protected override IModuleCatalog CreateModuleCatalog()
{
   ModuleCatalog catalog = new ModuleCatalog();
   catalog.AddModule(typeof(ModuleLogging));
   //I've not added ModuleItems as I want to check whether the user is authorized
   return catalog;
}   

What I've tried to call ModuleItems from ModuleLogging:

Uri viewNav = new Uri("ModuleItems", UriKind.Relative);
regionManager.RequestNavigate(RegionNames.TheUpperRegion, viewNav);
regionManager.RequestNavigate(RegionNames.TheBottomRegion, viewNav); 

But my LoggingView of ModuleLogging is not replaced by the ToolBarView of ModuleItems and DockingView of ModuleItems. I just see System.Object and System.Object respectively in ContentControls instead of controls as LoggingView is transparent.

Yeah, I know that there is no object in memory such as ModuleItems .

How to load module on demand and navigate to the views?

Upvotes: 3

Views: 6730

Answers (2)

StepUp
StepUp

Reputation: 38094

The greatest Magnus Montin helps me to solve the question:

This code is located at LoggingViewmodel of ModuleLogging:

private void DoLogin(object obj)
    {
        ShowAnotherView = false;
        if (UserName == "1" && UserPassword == "1")
        {                
            container.RegisterType<Object, TheUpperControl>("ModuleItems");
            Uri viewNav = new Uri("ModuleItems", UriKind.Relative);
            regionManager.RequestNavigate(RegionNames.TheUpperRegion, viewNav);
            regionManager.RequestNavigate(RegionNames.TheBottomRegion, viewNav);
            LoadTheOtherModule(); //load the other module
            var loginView = regionManager.Regions[RegionNames.TheWholeRegion].Views.ElementAt(0);
            regionManager.Regions[RegionNames.TheWholeRegion].Remove(loginView); //remove the login view
            //MessageBox.Show("");    
        }
        else
            ShowPromptingMessage = true;
    }

    private void LoadTheOtherModule()
    {
        Type moduleType = typeof(ModuleItems.ModuleItemsModule);
        ModuleInfo mi = new ModuleInfo()
        {
            ModuleName = moduleType.Name,
            ModuleType = moduleType.AssemblyQualifiedName,
        };
        IModuleCatalog catalog = container.Resolve<IModuleCatalog>();
        catalog.AddModule(mi);
        catalog.Initialize();

        IModuleManager moduleManager = container.Resolve<IModuleManager>();
        moduleManager.LoadModule(moduleType.Name); //run Initialize() of the other module
    }

It works like a charm!:)

Upvotes: 3

pangabiMC
pangabiMC

Reputation: 784

You may need to sort these to get it working properly:

  • Adding your module to the catalog
  • Loading the module on demand
  • Registering your view (or viewmodel) that will be shown in the region
  • Requesting the navigation to your view

Let's see in order

Adding your module to the catalog

I don't see any reason for not adding your module to the catalog, however what you probably don't want till after the authentication, is initialising the module. To get your Module initialised on demand you can add it to the catalog with the flag OnDemand:

The module will be initialized when requested, and not automatically on application start-up.

In your bootstrapper:

protected override void ConfigureModuleCatalog()
{
    Type ModuleItemsType = typeof(ModuleItems);
    ModuleCatalog.AddModule(new ModuleInfo()
    {
        ModuleName = ModuleItemsType.Name,
        ModuleType = ModuleItemsType.AssemblyQualifiedName,
        InitializationMode = InitializationMode.OnDemand
    });

Loading the module on demand

Then after the authentication succeeded you can initialise your module:

private void OnAuthenticated(object sender, EventArgs args)
{
    this.moduleManager.LoadModule("ModuleItems");    
}

where moduleManager is an instance of Microsoft.Practices.Prism.Modularity.IModuleManager (preferably injected to your class constructor)

Registering your view

You also need to register your view (or viewmodel if you're using viewmodel-first) you want to navigate to in the container. The best place to do this is probably the Initialisation of your module ModuleItems, just make sure the container is injected in its constructor:

public ModuleItems(IUnityContainer container)
{
    _container = container;
}

public void Initialize()
{
    _container.RegisterType<object, ToolBarView>(typeof(ToolBarView).FullName);
    _container.RegisterType<object, DockingView>(typeof(DockingView).FullName);
    // rest of initialisation
}

Note that in order to make the RequestNavigate to work you must register your view as an object and also you must provide its full name as the name parameter.

Also using the Module as the navigation target (like you did here: Uri viewNav = new Uri("ModuleItems", UriKind.Relative); is probably not the best idea. The module object is usually just a temporary object which is thrown away by default once your module is initialised.

Requesting the navigation

Then finally, once your module is loaded you can request the navigation. You can use the above mentioned moduleManager to hook to the LoadModuleCompleted event:

this.moduleManager.LoadModuleCompleted += (s, e)
    {
        if (e.ModuleInfo.ModuleName == "ModuleItems")
        {
            regionManager.RequestNavigate(
                RegionNames.TheUpperRegion,
                typeof(ToolBarView).FullName), 
                result => 
                { 
                   // you can check here if the navigation was successful
                });

            regionManager.RequestNavigate(
                RegionNames.TheBottomRegion,
                typeof(DockingView).FullName));
        }
    }

Upvotes: 8

Related Questions