如何在重新托管的工作流设计器中扩展上下文菜单?

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

我们正在使用一个重新托管的设计器(目前是 WF 4.0),其中包含许多自定义活动,它们都有自定义设计器。对于其中的一堆,我想在设计模式下将条目添加到设计器的上下文菜单中。我说的是这个菜单:

例如对于编码为 activity 的 XAML,我想要一个 "Open source..." 条目,它会将特定 activity 的 XAML 源加载到新设计器中。为此,我必须将条目添加到菜单中,并在单击时确定单击了哪个 activity。这两部分我都不清楚。我怎样才能做到这一点?

WF 3 中有 ActivityDesignerVerb class to do that. In WF 4 there seems to be workflowDesigner.Context.Services.Publish<ICommandService>(...),,但我不知道如何使用它向上下文菜单添加自定义操作。我该怎么做?

This SO entry 显示了一些用于内部调试器命令的内容,但我想添加一个全新的命令。

好的,您需要做的就是在自定义 activity 上实现 ICommand 接口。

因此,例如 - 从客户 activity class 公开自定义命令 属性,然后在构造函数中将委托事件应用于命令处理程序 -

/// <summary>
/// Custom activity
/// </summary>
public partial class CustomActivityDesigner
{
    /// <summary>
    /// Command used to display a dialog at design time
    /// </summary>
    public ICommand ShowCustomDialog{ get; set; }

    public CustomSchedulerDesigner()
    {
        InitializeComponent();

        ShowCustomDialog= new DelegateCommand(x => 
            //Do some stuff here that will display your dialog
            //you may want to consider passing the `this.ModelItem`
            //to your dialog so it can then interact with the ModelTrees etc
            //for example
            var dialog = new MyDialog(this.ModelItem);
            dialog.ShowDialog();
        );
    }

}

最后, 通过 activity 设计器 xaml.

将新命令连接到 UI
<sap:ActivityDesigner.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Show" Command="{Binding ShowCustomDialog}"/>
    </ContextMenu>
</sap:ActivityDesigner.ContextMenu>

宿主中解决

如果您想在工作流设计器主机上解决此问题,而不是在各个活动中,这样做非常简单直接。

当您托管工作流设计器并创建工作流设计器时,您只需访问其 ContextMenu 属性 并修改其 Items 集合。

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

如果您希望每个 activity 有不同的菜单项,您可以订阅 SelectionChanged 事件:

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

然后实现自己的逻辑:

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;
    }
}

在 activity 设计器中解决

如果您希望始终显示特定的上下文菜单项,而不管您的工作流设计器 UI 托管在何处,您可以在 activity 设计器 XAML 中创建自定义项:

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