Same module multiple times as TabItems

Jan 16, 2009 at 6:03 PM
Here's my scenario:
1) Shell with 1 TabControl and 1 region called MenuRegion
2) MenuRegion contains Buttons for each of the available modules (applications).

I need your help figuring out the following: When one of the buttons is clicked, I need to add a new TabItem to the TabControl, and load and individual instance of the corresponding module (application) inside this TabItem.
One module may appear several times in the TabControl.

Please help.
Jan 19, 2009 at 1:52 PM
I think the confusion here lies in your definition of a "module", and I would say that it originally confused a team in my company as well.  However, I may be wrong, and the definition you've acquired through guidance may be the exact same one that p&p is trying to portray.  Understand that my perceptions come from a CAB/SCSF-based world (and they have been equally effective in developing atop CAL) --

To me, modules are the byproducts of recognition (or intent to eploit) of observations found within the problem domain.  Depending on the project, I like to keep this entity-based for the first cut of segregation.  So we might have a Customers module and an Employees module.  Alternatively, module separation can be driven by user stories.  Modules, to me, then may contain many views and or controllers.  In CAL, I like to have one controller (serving as module controller if you will) for each module, and then at least one controller for each use case that module is intended to fulfill (sounds like SCSF doesn't it?).  During the execution of the application, these controllers could show any number of a myriad of views where no view is necessarily limited to a particular use case.

Using this understanding, I think what you actually want to achieve is this--

Given a use case (UC1) which consists of the user clicking a button and showing a tab with some information:

0) Boot app and show your Shell with some toolbar/ribbon region (region name of "Toolbar") and a central, tab control-based region (region name of "MainRegion") each with appropriately registered or default region adapters.
1) Load and Initialise a module "FooModule"
2) FooModule's initialisation executes an arbitrary method ("Run" is good) on a controller "FooController"
3) FooController resolves and runs another controller called "UC1Controller" who's purpose is to create and handle the components and events necessary for enacting UC1.
4) BarController subscribes some method (OnUC1Invoked) to a well known command that represents the execution of UC1.
5) BarController goes about registering a command invoking button (invokes UC1 via proper command binding) on the toolbar/ribbon by doing something like "RegionManager.Regions[RegionNames.Toolbar].Add(someButton)".
6) The OnUC1Invoked method resolves a" BarView" with a randomly generated id/name and adds the view to "MainRegion".

I think I've been fairly generous with my application of disclaimers thus far, but again, I'd like to state that I might be missing something from p&p's intent with CAL.  If I am misunderstanding how modules should be segregated or anything at all, please let me know.

Cheers and good luck

Jan 19, 2009 at 8:11 PM
Mike, I appreciate your response very much. In my case, a module is an entire application (they are small apps in general). For instance, it can be a employee management module, or a database management dashboard. Likely, they are not related.
Following your UC's step 0, I do not understand the concept of a "tab control-based region", and I think that's the core of my question. I am confused with the fact that I need to associate my view with a region by its name, and yet, the regions are to be created on-the-fly (as tabitems)...
So, can you please expand a little more on the tab control-based region you mention?
Jan 19, 2009 at 8:59 PM
Yup, very sorry I didn't also mention that a workbench style of application tends to create separate modules for sub-applications (though each of those applications could consist of multiple modules if designed right).

So your conundrum is more clear to me now ;)  I have seen it solved in two ways and I'd say one should be more preferred over the other

Don't do:
You could dynamically create a region name and assign it to the view dynamically.  If I recall correctly, the specifics are that the RegionManager's RegionName property is an attached property, (just like say Canvas.Top or Canvas.Left).  You would need some sort of service or event implemented to help declare to other components in the system that this new dynamic region is available.

Check out the documentation for CAL concerning scoped RegionManager's; basically, two regions can have the same name under certain conditions. Work out a strategy for utilising this in your framework.
Jan 19, 2009 at 9:01 PM
I might also add that you might want to consider using scoped Unity containers as well.  That is a lot of homework to do! ;)
Jan 20, 2009 at 12:02 AM
Thank you Mike. You gave me some good ideas and I will work on those.
I appreciate you help!
- Gus