How to change the CanExecute function after creating a DelegateCommand?

Topics: Prism v2 - WPF 4
Jul 19, 2010 at 11:56 AM
Just today I found a problem I would like to discuss here: After creating an instance of a DelegateCommand, I would like to replace the delegate I passed in for CanExecute. I haven't yet found out how to do this. First a small description of the WHY: I have a WPF4 app with a standard Microsoft Ribbon and I use PRISM MVVM v2.2. The application consists of more than one module and each module will add its tab to the ribbon. Each tab has its own viewmodel, which should act as a controller and respond to RibbonButton clicks by showing/hiding views. The Ribbon contains groups of buttons that belong together. Simply put, they are groups of 4 actions like Open, Add, Edit, Delete that work on the same items. I want the buttons to be enabled only when relevant, which means that the state of the Add, Edit and Delete actions should be managed by the ViewModel of Editor, which shows up after clicking the Open button. Depending on state of that view (is an item selected?), the Add, Edit and Delete actions shall be enabled. Now I implemented all 4 commands in the ViewModel of the ribbon and each command gets a default CanExecute delegate. When the Open command gets fired, it shows the view and binds a viewmodel to it. From that moment on, I would like the CanExecute methods to point to a method in the ViewModel. I don't see how to do this, since the CanExecute can only be passed in the constructor. Can anyone please advice if this is a handy way of working or how I can achieve my objectives more simple? I feels like it's all too complex and I learned that's generally an indication it should be done differently, but I do net yet see how... TIA, Jeroen
Jul 20, 2010 at 6:57 PM

This is one of the key scenarios that CompositeCommand was designed for. Hook your ribbon controls up to a CompositeCommand, make that accessible globally through a static or as named instances in the container, and then the modules can register and unregister new instances of DelegateCommands as needed to point to the transient actions that you want both called for CanExecute and called for Execute.

Have you looked into using CompositeCommand to address your needs?

Jul 21, 2010 at 6:23 AM

Thanks Brian, didn't think of that option yet. I saw the CompositeCommand in some places but had not yet realized it would be helping me here.
I already use DelegateCommands all over the application. Putting it as a named instance in the container is indeed the key to the solution. Thanks again!

Jul 26, 2010 at 9:58 PM

Hi Jeroen,

This is something not supported by the Prism’s DelegateCommand implementation out-of-the-box. That said, I think it might be achieved if you provide your own command class by implementing ICommand interface. This way, you would make accessible a CanExecuteMethod property, which can be updated with the method of you choice at anytime.

In addition, Globally Available Commands is the recommended approach by Prism, that could give you the ability of making your commands available, both in a module and cross-module. It might help you as this is not strictly necessary to use CompositeCommands, so you could provide your own implementation by exposing 4 instances of your custom ICommand over there. The implementation could be similar to the following code lines:

public static class GlobalCommands 
    public static ChangeableCanExecuteCommand OpenCommand = new MyCustomCommand(myOpenMethod);
    public static ChangeableCanExecuteCommand AddCommand = new MyCustomCommand(myAddMethod);
    public static ChangeableCanExecuteCommand EditCommand = new MyCustomCommand(myEditMethod);
    public static ChangeableCanExecuteCommand DeleteCommand = new MyCustomCommand(myDeleteMethod)

Additionally, take into account that if you have two of your editors open at the same time and you switch between them, you would need to update the CanExecuteMethod property and call the RaiseCanExecuteChanged method.

Please let me know if this helps.

Fernando Antivero

Jul 27, 2010 at 6:18 AM

Hi Fernando,

Thanks for following up on my post. I think your suggestion is a good one, using the Globally available
commands pattern does make sense, using either a static class or a IoC container.