workflow-foundation-4workflow-foundation-4.5

How to extend the context menu inside the rehosted workflow designer?


We are using a rehosted designer (currently WF 4.0) with a lot of custom activities, all of them have custom designers. For a bunch of them, I would like to add entries to the context menu of the designer when in design mode. I'm talking about this menu:

enter image description here

E.g. for a XAML coded activity I would like to have an "Open source..." entry which will load the XAML source of that specific activity into a new designer. To do that I must add the entry to the menu, and when clicked figure out on which activity it was clicked. Both parts are unclear to me. How can I achieve that?

In WF 3 there was the ActivityDesignerVerb class to do that. In WF 4 there seems to be workflowDesigner.Context.Services.Publish<ICommandService>(...), but I can't figure out how to use that to add a custom action to the context menu. How can I do that?

This SO entry shows something for internal debugger commands, but I want to add a completely new command.


Solution

  • Solving it in the host

    If you want to solve this on the workflow designer host, and not in the individual activities, it's quite simple and straightforward to do this.

    When you host the workflow designer and create the workflow designer, you can simply access its ContextMenu property and modify its Items collection.

    var wfd = new WorkflowDesigner();
    wfd.ContextMenu.Items.Add(new MenuItem() { Header = "Hello", Command = yourCommand, });
    

    If you want different menu items for each activity, you can subscribe to the SelectionChanged event:

    wfd.Context.Items.Subscribe<Selection>(SelectionChanged);
    

    And then implement your own logic:

    private void SelectionChanged(Selection selection)
    {
        // Remove old menu item
        if (oldMenuItem != null)
        {
            wfd.ContextMenu.Items.Remove(oldMenuItem);
            oldMenuItem = null;
        }
    
        var modelItem = selection.PrimarySelection;
    
        if (selection.SelectionCount == 1 && modelItem != null)
        {
            // Get activity type
            var activityType = modelItem.ItemType;
    
            var menuItem = new MenuItem() { /* ... */ };
            wfd.ContextMenu.Items.Add(menuItem);
            oldMenuItem = menuItem;
        }
    }
    

    Solving it in the activity designer

    If you want to always show a specific context menu item regardless of where your workflow designer UI is hosted, you can create a custom item in your activity designer XAML:

    <sap:ActivityDesigner.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Show" Command="{Binding YourCommand}"/>
        </ContextMenu>
    </sap:ActivityDesigner.ContextMenu>