Reputation: 38094
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
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
Reputation: 784
You may need to sort these to get it working properly:
Let's see in order
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
});
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)
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.
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