How To: Pass parameters to Commands Handlers in Composite UI Application Block (CAB) / SCSF
This week there were some questions in the SCSF Codeplex Forum asking for a way to pass custom parameters to a method marked as a Command Handler. As you may know, there is no out-of-the-box way to do it because they are raised internally by the Command class and, since you usually bind a command to a control event via the AddInvoker method, you cannot manage when the command is executed.
Additionally, the signature of a command handler is fixed and should always be like the following:
[CommandHandler(CommandNames.MyCommand)] public void OnMyCommandHandler(object sender, EventArgs args) { // The sender parameter is an instance of the Command class. Command cmd = sender as Command; // The args parameter is empty. bool f = (args == EventArgs.Empty); }
The instance of the Command class received in the sender parameter could be useful, for example, if you want to change the status of the command to Enabled, Disabled or Unavailable.
cmd.Status = CommandStatus.Disabled;
But, what if you want to share the same command handler for different command invokers (like several menu items) and perform some operations based on which item was the invoker? You will somehow need to receive a parameter describing which was the item that raised the command.
Workaround
A possible workaround to receive parameters using a command could be by not adding your items as invokers of the command and instead execute the command programmatically. If you do this, you could use the State collection of the RootWorkItem to pass parameters to the command.
To implement this workaround follow these steps (the code use the ToolStripMenuItem control but could be used with other toolstrip controls):
- Add the parameter that you want to receive in the command handler to the Tag property of your menu item control:
ToolStripMenuItem item = new ToolStripMenuItem() { Text = “My Menu Item”, Tag = “My Tag”};
- Add a handler for the Click event to your menu item:
item.Click += new EventHandler(Item_Click);
- In the Item_Click method, add the Tag of your item to the State collection of the RootWorkItem and execute the command programmatically:
WorkItem.RootWorkItem.State["LastTag"] = item.Tag; WorkItem.Commands[CommandNames.CommandWithParameters].Execute();
- In the command handler, retrieve the Tag from the State collection:
string tag = WorkItem.RootWorkItem.State["LastTag"] as string;
The following code shows a ModuleController class that demonstrates how the approach above could be implemented:
public class ModuleController : WorkItemController { public override void Run() { AddServices(); ExtendMenu(); AddViews(); } private void ExtendMenu() { AddTaggedMenuItem(“Menu Item 1″, “Tag 1″, UIExtensionSiteNames.ModulesMenu); AddTaggedMenuItem(“Menu Item 2″, “Tag 2″, UIExtensionSiteNames.ModulesMenu); AddTaggedMenuItem(“Menu Item 3″, “Tag 3″, UIExtensionSiteNames.ModulesMenu); AddTaggedMenuItem(“Menu Item 4″, “Tag 4″, UIExtensionSiteNames.ModulesMenu); } private void AddTaggedMenuItem(string menuText, string menuTag, string extensionSiteName) { ToolStripMenuItem menuItem = new ToolStripMenuItem() { Text = menuText, ToolTipText = menuText, Tag = menuTag }; menuItem.Click += new EventHandler(MenuItem_Click); WorkItem.UIExtensionSites[extensionSiteName].Add(menuItem); } private void MenuItem_Click(object sender, EventArgs e) { ToolStripMenuItem item = sender as ToolStripMenuItem; if (item != null) { WorkItem.RootWorkItem.State["LastTag"] = item.Tag; WorkItem.Commands[CommandNames.CommandWithParameters].Execute(); } } [CommandHandler(CommandNames.CommandWithParameters)] public void OnCommandWithParameters(object sender, EventArgs args) { string tag = WorkItem.RootWorkItem.State["LastTag"] as string; if (tag != null) { MessageBox.Show(“The tag received in the command handler is: ” + tag, “Tags”); } } // … }
In this way, the State collection is used as a container for your custom command parameters.
Enjoy.






