Suggestions for handling toolbar and menu buttons

Topics: Prism v4 - WPF 4
Apr 11, 2011 at 8:44 AM

Hi,

I’ve been wondering for a long time how to this problem with toolbars and menus for my Prism based application. This will be a very large application with lots of different functionality which is why it is important to get this right.

I need a menu with common items such as Exit (File) and Cut, Copy, Paste, Undo, Redo (Edit), etc. The same goes for the toolbar, where there’s a main toolbar with buttons for the same functionality.
For example the Save command has to be specific for the current active view, and only that. How would you handle this?

Now depending on the module, I need buttons that have common functionality for all views in that module. So when a view in a module gets requested, these buttons are added to the main toolbar, and when no more views from that module are active, the buttons are removed. Note that this is still the main toolbar – not a new toolbar in the same tray. How can I handle this adding and removing of buttons to the main toolbar? This main toolbar is defined in the Shell (with the buttons mentioned above).

Buttons that a very view-specific will be shown in their own toolbar so they should not be a problem.

I really hope that someone can help me see the solutions to these problems as they are a very important feature in our application.

Thank you very much!

Best regards,
Tommy

Apr 11, 2011 at 5:35 PM

Hi Tommy,

Based on my understanding of your scenario, you might find Commanding concepts handy.

In a composite scenario, the command handler is often a view model that does not have any associated elements in the visual tree or is not the focused element. To support this, Prism provides DelegateCommand, which allows you to call a delegate method when the command is executed, and CompositeCommand, which allows you to combine multiple commands. These commands are different from the built-in RoutedCommand, which will route command execution and handling up and down the visual tree.

CompositeCommands can be connected to several child commands.

For example your application could have global CompositeCommands that are defined in the shell that have meaning across modules, such as Save or Cancel commands. Modules can then register their local commands with these global commands and participate in their execution.

Additionally, you can read more about Commanding in Chapter 9: Communicating Between Loosely Coupled Components. Also, you might find the Commanding QuickStart useful.

Please, let me know if this information helps you.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic

 

Apr 11, 2011 at 5:46 PM
mbronzovic wrote:

Hi Tommy,

Based on my understanding of your scenario, you might find Commanding concepts handy.

In a composite scenario, the command handler is often a view model that does not have any associated elements in the visual tree or is not the focused element. To support this, Prism provides DelegateCommand, which allows you to call a delegate method when the command is executed, and CompositeCommand, which allows you to combine multiple commands. These commands are different from the built-in RoutedCommand, which will route command execution and handling up and down the visual tree.

CompositeCommands can be connected to several child commands.

For example your application could have global CompositeCommands that are defined in the shell that have meaning across modules, such as Save or Cancel commands. Modules can then register their local commands with these global commands and participate in their execution.

Additionally, you can read more about Commanding in Chapter 9: Communicating Between Loosely Coupled Components. Also, you might find the Commanding QuickStart useful.

Please, let me know if this information helps you.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic 


Hi Miguel,

Sorry if I didn't explain my problem correctly, but wiring up commands is not really my problem.

Let me try to explain it. What I'm trying to get a grasp on is how I can show and hide each button. It might be really simple, but I haven't been able to find much information about it.

Let's say that I have a toolbar with my common buttons such as Save. To this specific toolbar, i need to add other buttons from my modules. For example, I have a OrderModule with a view called OrderSummary. When this view is requested (or any other view in the OrderModule), I need to add a "New Order" button to this toolbar. When OrderModule no longer has an active view, the button should be removed again.

I was thinking about creating a "Service" with methods for adding buttons to this toolbar (the toolbar is defined in the Shell). But where should I control when to add and remove module-wide buttons?

Does it make any sense?

Apr 11, 2011 at 9:09 PM

Tommy,

One possible way to fulfill your goal could be set a region in the shell that can hold the buttons of the module, like a toolbar. When you load a module, in the Initialize method you could inject a view that holds these buttons that implements the specific functionality of your modules.

On the other hand, you can also read this thread where a similar requirement is achieved in order to manage a custom menu toolbar.

Thanks,

Miguel Bronzovic
http://blogs.southworks.net/mbronzovic

 

Apr 13, 2011 at 2:45 PM
Edited Apr 13, 2011 at 2:49 PM

Tommy,

Like I had posted before on the WPF forums you can do it fairly simply with a centralized approach with a couple of ObservableCollection<ControlType>'s and just bind the collection to the controls on the shell via the ShellViewModel at start up.  making them a region is kinda of more work than is necessary.  Then each module knows about the Service then and sends messages via the Service which sends the passed information to the subscribers in the ShellViewModel.

You could create a custom object (hell it could be string value, "viewmodelname:800", name for removal/grouping, value for sorting) assigned to the Tag property to allow for removal based on criteria which view is active.  When the view changes you would just run through your collection check the Tag property for the custom information and remove it if it matches accordingly.  Obviously you would need to make sure you global items aren't tagged with custom information so you accidentally don't remove them.

One thing I wanted to point out but didn't exactly have the best way to describe it.  I do use the MVVM Pattern but found that self-hydration of the Collections was cumbersome when responding to events so I moved the collections and the pub/sub to a Controller, the controller is responsible for the Hydration of Collections in the ShellViewModel then.  I hope that isn't confusing.  It just seemed cleaner overall.  It had code smell you could say.

 

Morgan.

Apr 13, 2011 at 3:56 PM
mvermef wrote:

Tommy,

Like I had posted before on the WPF forums you can do it fairly simply with a centralized approach with a couple of ObservableCollection<ControlType>'s and just bind the collection to the controls on the shell via the ShellViewModel at start up.  making them a region is kinda of more work than is necessary.  Then each module knows about the Service then and sends messages via the Service which sends the passed information to the subscribers in the ShellViewModel.

You could create a custom object (hell it could be string value, "viewmodelname:800", name for removal/grouping, value for sorting) assigned to the Tag property to allow for removal based on criteria which view is active.  When the view changes you would just run through your collection check the Tag property for the custom information and remove it if it matches accordingly.  Obviously you would need to make sure you global items aren't tagged with custom information so you accidentally don't remove them.

One thing I wanted to point out but didn't exactly have the best way to describe it.  I do use the MVVM Pattern but found that self-hydration of the Collections was cumbersome when responding to events so I moved the collections and the pub/sub to a Controller, the controller is responsible for the Hydration of Collections in the ShellViewModel then.  I hope that isn't confusing.  It just seemed cleaner overall.  It had code smell you could say.

 

Morgan.


Exactly. Did you ever see my response on the WPF forum? :-)

Do you have a sample implementation for that "custom" object? It seems a bit hacky to me, but I might be wrong about it.

Apr 14, 2011 at 4:56 PM

I did :)

As for the custom object right now I am just using a Integer value for sorting of the root menu items. Then just using a linq query + a loop to replace / insert the menu items.  Also, you understand I don't remove from the menu ever since my current setup is a TabControl (MainRegion) for displaying content and I load data automatically on load.  I will probably help this alittle with some reactive framework calls for an async feel, to make sure the UI isn't unresponsive, while the data is being pulled in.

For the object you could use a 2 property class which is assigned to the Tag property (which is object type).  Then just do some linq magic to do the inclusions/exclusions.

I might being to the it most elegant way but it serves its purpose and works.  I can say that I did do some searching all over for examples, did come across a few, but they did end up re-creating a new class with menuitem being part of it.  They didn't feel very adaptive.  I will probably work on something slightly better but this stuff atm isn't my day job.