Modular Navigation Question

Topics: Prism v4 - WPF 4
Nov 27, 2012 at 12:02 PM

Hi all

I am trying to learn how to architect a modular application in WPF 4 using PRISM 4.

Using Unity container to register and inject my types, I have got a shell application and have created a single module which automatically loads. The "landing page" of my created module is a user control has a number of buttons to allow the user to access the area of the module concerned. My questions are

  • Upon clicking one of these buttons how would I get the User control/view associated to this area of the module to load in the MainRegion I have defined in the shell application? I have my <Module>MainView & associated viewmodel & interface. In the view model I have a DelegateCommand created but what goes in here?
  • Then how would I go back to the "landing page" when user has finished processing in the previous area?
  • How do I have multiple modules in my solution and load a specific module from a "Main" startup module dependant on user selection?

Sorry if these are daft questions but Can't seem to get head away from button click = Frame.Navigate????????

Any help appreciated.

Thanks

 

Nov 27, 2012 at 4:52 PM

OK, carried on looking and have modified my application to have the following structure:

 

  • Management.Desktop wpf aaplication with shell window. This calls Bootstrapper class(Unity) and registers my modules, ModuleA is set to load on demand whilst ManagementMainModule is initialised straight off the bat.
  • ManagementMainModule
    • This has a MainView & MainViewViewModel with commands bound to buttons for launching other modules. Have injected the IModuleManager and called the LoadModule("ModuleA") method to load my other "A" module
  • ModuleA
    • ModuleA has a main UserControl with buttons to load the various views within this module, again commands bound to the buttons
    • I can load the various views but am unsure how to get my ManagementMainModule to show back in my MainRegion upon "exiting" my ModuleA, surely ModuleA does not need to know about the ManagementMainModule to activate this view in the ContentControl of my app?

Question is essentially, once I've finished with a module, how do I go activate the "original" main modules' MainView?????

Developer
Nov 27, 2012 at 6:09 PM
Edited Nov 27, 2012 at 6:09 PM

Hi,

Prism provides you with several approaches to dynamically compose your UI using Regions. If you want to switch the MainView that is in the MainRegion with another view, when a button of the aforementioned MainView is pressed, you could use the view injection or the navigation  approaches provided by Prism. For example, in the method executed by the DelegateCommand, you could perform a navigation request like this:

// After loading ModuleA
_regionManager.RequestNavigate("MainRegion", "ModuleAView");

Then, when you need to go to the MainView again, you can simply perform another navigation request to the MainView. Like this, the modules do not need to know each other, as the navigation approach provided by Prism use URIs to identify the views.

Also, Prism provides you with a RegionNavigationJournal which allows you to navigate back and forward between the different navigation request that were performed in a specific region. For example, if you navigated from your MainView to the ModuleAView, you can navigate back to the MainView simply by invoking the Journal's GoBack method of the NavigationService of the MainRegion. However, in order to be able to use this, the MainView should be also navigated the first time, instead of being registered using the RegisterViewWithRegion method. For example, in the Initialize method of the ManagementMainModule you could navigate to the MainView doing something like this:

// After registering the components in the container 
_regionManager.RequestNavigate("MainRegion", "MainView");

Take into account that in order to use your views with Prism's navigation capabilities you need to register your views in the container to be used in navigation. For example, in Unity, a view must be registered like this:

container.RegisterType<object, MainView>("MainView");

You can find more information about navigation and other UI composition capabilities provided by Prism in the following chapters of the documentation:

I hope you find this useful,

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

Nov 28, 2012 at 10:49 AM

Cheers for response DC. Can I question this part?

"Then, when you need to go to the MainView again, you can simply perform another navigation request to the MainView. Like this, the modules do not need to know each other, as the navigation approach provided by Prism use URIs to identify the views."

My thinking was that I would have a "Done/Close" button in my ModuleAView which indicates to me that the user is finished with this module. If I had a command in my ModuleAViewViewModel which had the _regionManager.RequestNavigate("MainRegion", "MainView"); line this implies that my ModuleA can only ever be loaded into an application which actually had a MainView is this right? I thought the idea of modularisation was I could consume my module in any calling app, within reason? Would this be saying "you can consume in any app which has a MainView delared and registered in the regionManager"?

Thanks again.

 

Developer
Nov 28, 2012 at 4:31 PM

Hi,

Based on my understanding in some scenarios modules may depend on other modules, as they could require components provided by other modules to function, without knowing their specific implementations. Hence, it will depend on your preferences and the requirements of your scenario, how these modules will be integrated together into the main application.

It's true that calling the _regionManager.RequestNavigate method in you ModuleA's view model, will require having a MainView registered in the application. Although, this will not make your module dependent of any specific implementation of this view, it will require one in order to function properly.

Hence as an alternative, I believe, using another loosely coupled communication mechanism could become handy if you want your modules to be more independent, for example you could publish an event using the EventAggregator when closing the opened module's view. This way your main module could be subscribed to this event and react showing the MainView again when necessary. Like this your module doesn't need to know of the existence of a MainView. For more information about the use of the EventAggregator you could check the following chapter of the Prism documentation:

I hope you find this helpful,

Agustin Adami
http://blogs.southworks.net/aadami

Nov 29, 2012 at 9:36 AM

Great input, cheers Agustin.