Archive for February, 2009

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):

  1. 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”};

  2. Add a handler for the Click event to your menu item:
    item.Click += new EventHandler(Item_Click);
  3. 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();
  4. 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.

Migrating Prism v2 Silverlight applications from static to dynamic module loading

The P&P Sustained Engineering Team has published an article in the Composite WPF & Silverlight Knowledge Base that explains how to modify the Prism v2 Silverlight Reference Implementation so it uses Dynamic Module Loading. By doing this, each module generates its own XAP file and the ModulesCatalog.xaml file in the Shell project defines how modules should be loaded:

As I mentioned, the article targets the migration of the Silverlight Reference Implementation included in the Prism V2 - Drop 10, but you could use it as a guidance to migrate any Prism v2 Silverlight application from static to dynamic (remote) module loading. The main steps are:

  1. Update Silverlight class library projects to Silverlight application projects to generate XAP files
  2. Set up remote module loading by adding a ModulesCatalog.xaml file and modify the Bootstrapper class
  3. Create a Web Application Project to host the application

The team also published the following:

  • The PDF version of the article
  • The updated source code of the Silverligh RI
Disclaimer: The code is provided “AS IS” with no warranties, and confers no rights.