I try to create an application that has a window behaviour as MS Office, for example Word/Excel. The user opens the application and when clicking new, a completely new window shall appear with the look of the application.
The closest that I found so far is this: Link
However, here the shells are shown at application start. How to do this by command, or maybe there is a completely different way to achieve this?
Edit: I have also found the following now: Link, but where and how to call this code?
Creating multiple shells is the correct idea. You just need to take care of the details appropriately.
When and how to create a new Shell
The Prism way is, of course, to have a
DelegateCommand
handle the creation of a new shell. Considering that this command does not strictly belong to any particular ViewModel (I 'd say it has an application-wide scope), it feels better to me to have apublic static class ApplicationWideCommands
with aCreateNewShellCommand
static property. You can then either bind to it from XAML with{x:Static}
or execute it from code-behind as needed.This command would need to take care of two things:
Window
(actually, aShell
)IRegionManager
for the new shell, so that there is no conflict in region names between the regions in the existing shell and those in the new shellIRegionManager
I 'll tackle this last-to-first, because it's easier to explain.
Giving your new Shell a new RegionManager
When declaring a region in Prism you can declare the region manager to use in addition to the region name. Normally you don't need to do this, but here we need to choose which
RegionManager
to use because region names must be unique in the scope of a single region manager. Since the region names are hardcoded inside the XAML of the Views, and it would be a major pain to assign them another way, we need to change the other half of the equation: the region manager instance used by each shell. So insideShell.xaml
there might be something like this:This will instruct the "WorkspaceRegion" in each shell that it belongs to the
IRegionManager
provided by the binding. Since the shell usually has noDataContext
, we can declare theRegionManager
property in the shell class itself:So now we just need to make sure that each
Shell
instance gets its ownRegionManager
. For the "first" shell, this will be done by theBootStrapper
. (The code below uses the DI container to resolve objects, and the examples use theUnityContainer
. If you use MEF for dependency injection just mentally translate to the equivalent code.)For the other shells, it will be done by the
CreateNewShellCommand
:There is an important caveat here: The
RegionManager
is registered into the container as a singleton. This means that whenever you resolveIRegionManager
you will be getting back the same instance. For this reason, we create a new instance by calling theIRegionManager.CreateRegionManager
method (this applies Prism v4; I 'm not sure about v2).At this point, you know how to create any number of new
Shell
instances and wire up the regions accordingly.UI composition details
The final detail you need to take care of is that all regions hosted in each shell, no matter how deep in its visual tree, have to bind to the same
RegionManager
.This means that you have to explicitly set the region manager to use like we did in the
ContentControl
example above for all regions in all Views in your application. Fortunately, this is done quite easily because:Shell
in the visual treeShell
already exposes the correctRegionManager
as a property, so we can bind to thatYou would do so like this:
All set!
You now should be ready to go.
Here the implementation that I now use to create multiple Shells with multiple EventAggregators. I pass the container in the bootstrapper. In my special case, the sub-module listens to the event in order to get the path parameter on which this Shell operates. The sub-module can then create the node data file at the path location or load from the path location depending on the parameter details.