Access the shell from modules

May 28, 2008 at 9:17 AM
How can you access the shell from modules?
I have a menu in my shell that I want to add some menuitems to from loaded modules.
May 28, 2008 at 10:45 AM
Hi Kiarz,

The way I am currently handling this situation is to create a Service in the Infrastructure project that deals exclusively with manipulating the Shell UI. I've called it ShellExtensionService, and once registered on startup I can resolve and instance of it from any module and call various methods to update menus, status bars etc in the Shell.

I've got a post just under yours questioning whether this is the best way to do this in prism (it's certainly how it was done in CAB).

If you want any more help with this, feel free to contact me.


May 28, 2008 at 12:14 PM
Hi Justin,

Thanks for the response.
I handled the problem by using events. Every time a module wants to f.e. add a new menu item, it fires the event which shell has subscribed to.
But your solution seems more appropriate.

May 28, 2008 at 11:58 PM
If you wouldn't mind, could you please post a sample of how you created the ShellExtensionService.  I don't have a great handle on working with the services.

May 29, 2008 at 2:25 AM
Edited May 29, 2008 at 2:37 AM

Hi Ben,

Here is rough example of how my Service works. It assumes you have a common View with a Toolbar in it and you want to add buttons to that toolbar.

Here is the service itself:

 public class UIExtensionService : IUIExtensionService

  private IToolbarPresenter _toolbarPresenter;

     public UIExtensionService(IToolbarPresenter toolbarPresenter )
          _toolbarPresenter= toolbarPresenter ;


      #region IUIExtensionService Members  

      public void AddLauncherItem(string text, string itemId)
           _toolbarPresenter.AddToolbarItem(text, itemId);


Then in your ToolbarPresenter class you simply fill in the AddToolbarItem method to do whatever it is you want to do. E.g.

    this.View.Toolbar.AddItem(text, itemId);

You add the following to your container configurator

    container.RegisterType<IUIExtensionService, UIExtensionService>(new ContainerControlledLifetimeManager());

Then to add to the UI from within your module, in the Initialize() for example you add

    IUIExtensionService uiExtender = this._container.Resolve<IUIExtensionService>();
    uiExtender.AddToolbarItem("Sites", Guid.NewGuid().ToString());

Hope this helps. Give me a shout if you want to know any more.



Jun 1, 2008 at 11:08 PM
Edited Jun 1, 2008 at 11:38 PM
Another approach is to use Regions and templates. As in the new drops the default regions for displaying items are item controls.

1. Add an items control to your view and mark it as a MenuRegion.
2. Create a new model UICommandModel (or whichever name you choose) to represent each item in the menu. The model should contain a Command property of type ICommand. It may also contain additional things such as IconURI, Description, etc.
3. Create an ItemsTemplate for the ItemsControl that will render the UICommandModel appropriately for example as a toolbar button. As part of the template call the underlying command on the model i.e. <Button Command="{Binding}"/>.
4. In your module(s) you can now grab the "MenuRegion" through the RegionManager. Create instances of UICommandModel and then add them to the region. Instantly you will see the menu items appear.

You can also use an alternative approach of passing around a shared model and rendering that model with templates. This is similar to using the region approach, only instead of uisng the RegionManager and the methods on the IRegion interface, you are simply directly accessing the model.

1. Create the UICommandModel described above. 
2. Create a MenuModel which contains a MenuItems property of type ObservableCollection<UICommandModel>.
3. Create an ItemsControl which will represent the menu.
4. Create an ItemsTemplate for rendering UICommandModel including binding to the UICommand.
5. Set the ItemsControl source to the MenuModel.MenuItems.
6. Register the MenuModel in the container.
7. In your module inject the MenuModel as a dependency.
8. Add / Remove UICommandModel instances to the model and voila, the menu will update.
Jun 2, 2008 at 3:21 AM
I think I prefer Glenn's method better than my own. It's definitely more WPF-y.
Jun 2, 2008 at 12:31 PM
Hi Glenn,

<Another approach is to use Regions and templates. As in the new drops the default regions for displaying items are item controls.>

i think this is a very interesting approach and lot#s of people are interested about this.
.Can you post some code?

Jun 6, 2008 at 3:42 AM
Hi Peter,

Since Glenn is at Tech Ed. preaching the gospel of PRISM I thought I'd post my implementation of what he's suggested for your perusal. I hope you find it useful.

A little bit of background. I have a shell that allows multiple "instances" of the main view of module to be shown in a main region. To allow for switching between these I have a control very similar to the windows task bar. I.e. When the module adds a view, I want a button on the task bar that will reactivate that view should I switch away from it later.

So - first thing, is the task bar itself which appears in Shell.xaml. As Glenn suggested this is just an ItemsControl

                <ItemsControl prism:RegionManager.RegionName="Taskbar">
                            <StackPanel Orientation="Horizontal"/>
                        <DataTemplate DataType="{x:Type UIModels:TaskbarItemModel}">
                            <Button Height="26" Content="{Binding Text}" Command="{Binding Command}" CommandParameter="{Binding Parameter}"></Button>

You can see that this will basically be represented as a Horizontal Stack Panel. The important part is the ItemTemplate which targets my custom class called TaskBarItemModel. The class definition for this class looks like this:
using System.Windows.Input;

namespace MyProject.Infrastructure.CommonUI.Models
    public class TaskbarItemModel

        public string Text

        public ICommand Command

        public string Parameter

The final piece of the puzzle is to actually add an item when a view is put in the main region. I have a ShowModule() method that includes the following code

protected void ShowModule()
this._regionManager.GetRegion("MainRegion").Add(myPresenter.View as UIElement, myPresenter.View.Id, true);


TaskbarItemModel taskbarItem = new TaskbarItemModel()
    Text = "Site",
        Command = ActivateViewCommand,
        Parameter = sitePresenter.View.Id


The ActivateViewCommand you see in the above method is just a delegate command that takes a string:

public DelegateCommand<string> ActivateViewCommand { get; private set; }

In my constructor for the module I initialize it like this:

ActivateViewCommand = new DelegateCommand<string>(ActivateView);

ActivateView is just a method that handles my view activation logic

private void ActivateView(string viewId)
            //stuff gets done here to reactivate an existing view

So with those few little pieces of code you will basically end up with a ItemsControl filled with TaskbarItemModels, however, what appears on the screen is a StackPanel filled with buttons where the command calls back to a method within a the moduel that added the button.

I hope this is helpful to you, please let me know if there's anything I ahven't made clear.



Jun 7, 2008 at 8:59 AM
Hi justin,
thanks a lot. Your post was very helpfull. for me and i think for other users of prism as well

Jun 8, 2008 at 2:57 PM
Thank you for all your input.  I have been playing with this in my app prototype.

I have successfully added a toolbar as suggested above.  When taking these suggestions and applying them to a menu, you end up with a nested menu item.  The menu will place a menuitem wrapper around the ItemsControl.  I found this artical that discusses a similar problem.
"Three Ways to Create Dynamic Menus"

I am looking into creating my own custom region based on wrapping MenuItem.  The only problem is this still doesn't give me exactly what I would like.  My ideal world would consist of being able to specify in the module the suggested parent MenuItem.  If it exists, it would attach my menu item to it.  If it doesn't create it at that level.  This way I can have a dynamic module that can have it's own sub menu item, and any modules it loads can attach to this sub menu item.

For example:
File        Reports
  Exit        Clinic Reports <<Clinic Module it the parent menu>     
                Report1  <<Report from sub-module1 loaded from Clinic Module>>
                Report2  <<Report from sub-module2 also loade from Clinic Modules>>

The Main parent module should not need to know that Clinic Reports is one of the menuitems.

Does anyone have any other suggestions on adding to the menu with out creating a new region wrapper or any additional comments/suggestions on creating a dynamic menu without building my own menu control?

Jul 14, 2008 at 3:52 PM
Hi Ben

Did you have any luck with this?

I'm just starting on a prototype app and I would like my menus to do exactly as your example shows.

Jul 9, 2009 at 2:41 PM
Edited Jul 9, 2009 at 3:07 PM

Glenn's solution works only if all your Regions are at the top level, meaning the region containing the toolbar is not nested (as in a ControlTemplate) inside of another region, eg.


                   - NestedToolBarRegion (within the ControlTemplate of MainRegion's host)


In that case the RegionManager cannot resolve the nested region and causes an exception with a message like "This RegionManager does not contain a Region with the name 'NestedToolBarRegion'"


Just a caveat to remember


Jul 15, 2009 at 3:26 AM

"Glenn's solution works only if all your Regions are at the top level"

This is not technically true, you could easily register the nested RegionManager for resolution upon it's creation and resolve it further down the tree.