我很难让我的自定义活动设计师在工作流设计器中显示。我的活动包括一个活动功能,我已经找到了许多博客文章,其中涉及here,here,here和here。
自定义活动有ActivityFunc<>
作为输入参数,我需要在设计器中将func公开为放置区域,用户可以在其中放置“内部”活动(àla TransactionScope
)。
自定义活动是在XAML中创作的,func的声明如下所示:
<x:Property Name="CompletionTest" Type="ActivityFunc(sdscmt:DmeTask, sdsav:WfPatient, sdscmc:DmeClinicalElement, x:Boolean)" />
XAML还包含与InvokeFunc<>
属性匹配的CompletionTest
活动。
活动设计师遵循上面提到的博客文章中列出的建议。特别是,它会覆盖OnModelItemChanged
以初始化CompletionTest
属性:
if (this.ModelItem.Properties["CompletionTest"].Value == null)
{
this.ModelItem.Properties["CompletionTest"].SetValue(
new ActivityFunc<DmeTask, WfPatient, DmeClinicalElement, bool>()
{
Argument1 = new DelegateInArgument<DmeTask>
{
Name = "task"
},
Argument2 = new DelegateInArgument<WfPatient>
{
Name = "patient"
},
Argument3 = new DelegateInArgument<DmeClinicalElement>
{
Name = "element"
},
Result = new DelegateOutArgument<bool>
{
Name = "success"
},
});
}
设计师的XAML看起来像这样:
<sap:ActivityDesigner x:Class="SoftInfo.Dme.ServicesDme.Workflow.Design.PerformTaskDesigner" ... >
<StackPanel>
<sap:WorkflowItemPresenter AllowedItemType="{x:Type sa:Activity}" Background="Transparent" MinWidth="150" MinHeight="100" HintText="Drop the completion test here" Margin="5,5,5,5" Item="{Binding Path=ModelItem.CompletionTest.Handler, Mode=TwoWay}" />
</StackPanel>
</sap:ActivityDesigner>
毕竟,每当我将自定义活动的实例放入工作流程时,我会得到一个标有“无法生成PerformTask视图”的红色框,我的设计师应该出现在该框中。框的工具提示表明设计师内发生了异常:
System.Windows.Markup.XamlParseException: A 'Binding' cannot be set on the 'Item' property of type 'WorkflowItemPresenter'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
我不明白我做错了什么。之前我曾多次使用WorkflowItemPresenter
,这是我第一次遇到此绑定错误。
答案 0 :(得分:0)
这是一种搞砸的方式来解决这个问题。错误可能不正确;内在的例外会告诉我下注的故事(对不起,在我今天工作的时候听“权力的游戏”)。
我实施IActivityTemplateFactory来配置我的活动代表:
public sealed class MyActivity: NativeActivity, IActivityTemplateFactory
{
public const string ChildArgumentName = "theArgument";
public ActivityFunc<object, bool> Child { get; set; }
Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
{
return new MyActivity()
{
Child = new ActivityFunc<Capture, bool>
{
Argument = new DelegateInArgument<object>(ChildArgumentName )
}
};
}
}
请注意这里有几件事。是的,设计界面实例化了一个Activity的实例,只是用它来创建同一个Activity的另一个实例(当然配置得当),但这个方法是防弹的。如果要求,您可以将IATF的实施移至其他地方,但如果谁关心并不重要?
请注意,我在Activity的设计中声明了Func参数的名称。您可以以更通用的方式(自定义属性等)执行此操作,但如果您的活动以可预测的方式组合在一起,我发现这是自动将子活动与其父项连接起来的最简单方式。 YMMV。
在设计师中,它的相似之处在于:
<sap:WorkflowItemPresenter
HintText="Add child here"
Item="{Binding ModelItem.Child.Handler}" />
这就是你所需要的一切。如果活动的签名不匹配,则不适合。孩子还利用IATF将自己绑定到其父级:
public sealed class ChildActivity : NativeActivity<bool>, IActivityTemplateFactory
{
public InArgument<object> Target { get; set; }
Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
{
return new ChildActivity
{
Target = new VisualBasicValue<object>(MyActivity.ChildArgumentName)
};
}
}
如果您希望将您的子Activity放在不同的目标上,您可能需要对target
DependencyObject
进行一些烦人的检查,这将允许您检查当前的工作流树。 (请注意,我不是100%熟悉VisualBasicValue的隐式转换行为,因此上面的代码可能会有一些编译器错误!)
另一个选择是,如果你必须特别棘手(从工具箱中删除一个Activity,然后将它拖到你必须重新进行检查的其他地方)就是从CacheMetadata中检查工作流的当前状态。我没有这样做,但我相信您可以使用设计图面更新您的注册,以反映工作流程的当前状态。