multiple view on tab region with sub region

Topics: Prism v4 - Silverlight 4
Sep 21, 2012 at 9:36 AM
Edited Sep 21, 2012 at 9:41 AM

Hi

I am new on developing silverlight with Prism.

I already made some reseach on how to my problem with the region and subregion with multiple instance of same view to the tab region but still I can't find the answer.

I have main project module  with 1 View and has TabControl as a prism region.
Then, I have separate sub projects module with a view and inside of the view it also has a region.
The way I call the sub project module is using requestnavigate.

_regionManager.RequestNavigate("TabRegion", New Uri("Module1", UriKind.Relative), AddressOf NavigationCompleted)


Whenever I use the RequestNavigate to call the view of the sub projects, it is add to the tabitem of the main project module. This is working. But when I call again the navigaterequest to add the view of the sub project module that is already added on the tabitems, instead of create a new tab and instance of the view, it prompts an error like this.

"An exception occured while creating a region with name 'exampleregion'. The exception was: System.ArgumentException: Region with the given name is already registered".

I read from one of the article, I need to use the injection of view to have multiple instance of the view and put different name of the view.
Example
Dim mainRegion = RegionManager.Regions("TabRegion")
mainRegion.Add(new OrderDetails(), "OrderDetails1")
mainRegion.Add(new OrderDetails(), "OrderDetails2")

I can't use this code to the main project module to call the views of the sub project module. The main project module cannot find the views of the sub project module because it is on separate project. In the example above, the OrderDetails cannot be find on the main project module because it is located on the sub project module.

Normally, my sub project module register its view on the moduleinit like the example below and I can call it to the main project module using requestnavigate.

 

 Public Sub Initialize() Implements Microsoft.Practices.Prism.Modularity.IModule.Initialize
_container.RegisterType(Of Object, SubModuleView)("SubModuleView")
End Sub

 


I hope someone can help on how I can solve my problem.

 Here is my sample project https://www.dropbox.com/s/pe5y31iuhpg9h9y/TestProject.zip  that has similar problem.

 

Developer
Sep 25, 2012 at 3:22 PM

Hi,

Based on my understanding of your scenario, the cause of the error your are receiving is that the RegionManager allows only uniquely named regions; therefore, the second registration of the same region name would produce the error you mentioned. Hence the problem may be that you are adding views that contains regions with the same name and not the name of the views itself. In order to avoid this, I believe you could benefit of the Scoped Regions functionality provided by Prism,  which allows that each view will have its own RegionManager so that the inner regions will be registered with that RegionManager rather than the parent RegionManager.

For more information about this you could check the following section of the Prism documentation:

As explained in the documentation, scoped regions in Prism are only available with view injection as out of the box, hence you will have to add views using this approach, similar like the code snippets you posted above but setting the createRegionManagerScope parameter to true when calling the Add method. Note that when using this parameter set to true, the Add method will return the new RegionManager that you can retain for further access to the local scope in order to change the content of the inner regions.

On the other hand, if the view you want to add are located in a different module, you could retrieve them by resolving the corresponding instances from the container. For example, based on your sub project module registration example, you could resolve the SubModuleView like this:

 

Dim myView As Object = _container.Resolve(Of Object)("SubModuleView")

 

Then you could add this instance to the region instead of directly creating a new one which will require a reference to your module.

Also you could register you views through a common interface that could be used to resolve the views across you different modules. For more information about this I recommend you to check the following chapter of the documentation:

I hope you find this handy,

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

Sep 27, 2012 at 2:51 PM
Edited Sep 27, 2012 at 3:43 PM

Hi 

Thank you for your answer. It helps me a lot. I already tried the view injection and your example to resolve the sub module view. I can now create multiple instance of view on the tab region.

Now,  I am facing a new problem. In my SubModuleView, I also have region (SubModuleViewRegion) and 2 buttons to load view1 and view2 to the region. 

When I click the button, I encountered this error

"The region manager does not contain the SubModuleViewRegion".

This is the code on the button to the viewmodel of SubModuleView

Dim mainRegion = _regionManager.Regions("SubModuleViewRegion")       
Dim subModule = _container.Resolve(Of Object)("View1")       
mainRegion.Add(subModule, "View1", True)

 

You can find my updated codes here

https://www.dropbox.com/s/lkyhdh0wdlfoin0/TestProject.zip

Developer
Sep 27, 2012 at 9:42 PM

Hi,

After analyzing your updated sample we found that the cause of the error is that region you are trying to retrieve is contained in a scoped RegionManager, but you are asking that region to the parent RegionManager. As each RegionManager is unaware of the regions of the others, you will need to obtain the region thought the corresponding scoped RegionManager.

When retrieving a RegionManager from the container through dependency injection, the container will inject the parent RegionManager, as it's the only RegionManager the container knows. Therefore, in order to access the scoped RegionManager in the SubModuleViewModel, you will need to implement the logic to save this RegionManager and to retrieve it in the view model.

As a possible approach for doing this, I believe you could check the Prism Training Kit - UIComposition Lab. This lab portrays a case where scoped regions are used. Although the labs are in C#, I believe you could find the approach used to handle the different RegionManager instances useful in your application.

Regards,

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

Sep 28, 2012 at 9:16 AM
Edited Sep 28, 2012 at 2:52 PM

Hi

I understand that I need to implement to save the regionmanager and retrieve it in the view model.
I got confused on the code from Prism Training Kit. Maybe because the example is in C# and Model View Presenter.

The model view presenter is really new to my knowledge. As much as possible, I would like to not change the way I code my project with Model View ViewModel (MVVM).

I hope we could make it work using my submitted sample project. 

Thank you in advance for the help.

Developer
Sep 28, 2012 at 9:15 PM

Hi,

In order to avoid changing the structure of your project, I believe you could take advantage of the RegionManagerAwareBehavior and the IRegionManagerAware interface I wrote in the following blog post:

Basically, when a view / view model that implements the IRegionManagerAware interface is injected in a region, the RegionManagerAwareBehavior will automatically set its RegionManager property to the corresponding RegionManager of that view / view model. For example, in the SubModuleViewModel, the RegionManager property will contain the scoped region manager. Therefore, I believe that by using this behavior you can achieve the functionality you need without making major changes.

Unfortunately, the behavior's code is written in C#; however, I believe you should be able to port it to VB without problems.

In order to add the behavior to your application, you only need to override the RegisterDefaultRegionBehaviors method of the Bootstrapper and then implement the IRegionManagerAware interface in the view models that need to access it's corresponding RegionManager (e.g. the SubModuleViewModel).

You can find more information about registering behaviors this in the following section of the Prism documentation:

I hope you find this useful,

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