2011-10-07 75 views
0

我有一个很难得到我的一个自定义的活动设计器中的工作流设计器以显示。我的活动包括活动FUNC,我已经发现了一些与他们打交道herehereherehere博客帖子。绑定错误<>

自定义活动具有ActivityFunc<>作为输入参数,并且我需要以暴露在FUNC设计者作为其中用户可以将一个“内”活性(点菜TransactionScope)放置区。

定制活动创作的XAML和FUNC的声明是这样的:

<x:Property Name="CompletionTest" Type="ActivityFunc(sdscmt:DmeTask, sdsav:WfPatient, sdscmc:DmeClinicalElement, x:Boolean)" /> 

的XAML还包含一个InvokeFunc<>活动相匹配的CompletionTest财产。

活动设计遵循上述mentionned的博客文章中概述的建议。特别是,它会覆盖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

这类型的搞砸的路要走这一点。错误可能不正确;内在的例外会告诉我会下注的故事(对不起,我今天工作时听着权力的游戏)。这里

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

注意两件事情:

我实现IActivityTemplateFactory配置我的活动委托。是的,设计图面将实例化一个Activity的实例,仅用它来创建同一个Activity的另一个实例(当然是正确配置),但是这种方法是防弹的。如果需求决定,你可以在其他地方将你的IATF实施移到其他地方,但是如果没有关系谁在乎呢?

请注意,我在我的活动设计声明函数功能的参数的名称将是什么。你可以用更通用的方式(自定义属性等)来做到这一点,但如果你的活动以可预见的方式组合在一起,我发现这是自动将孩子活动与父母联系起来的最简单方式。因人而异。

在设计,它类似于:

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

如果你希望你的孩子的活动在不同的目标被丢弃,你可能需要做targetDependencyObject的一些恼人的检查,这将使您检查当前的工作流程树。 (请注意,我并不是100%熟悉VisualBasicValue的隐式转换行为,因此您可能会在上面的代码中遇到一些编译器错误!)

另一个选项,如果您必须特别棘手(将一个Activity从工具箱,然后将其拖到其他地方,您将不得不重新进行检查)是从CacheMetadata内检查工作流的当前状态。我没有这样做,但我相信你可以更新注册与设计界面,以反映当前的工作流程状态。

+0

谢谢。我熟悉'IActivityTemplateFactory',但没有在我的问题中提到它,因为无论我的自定义活动是否实现它,我都会得到相同的错误。我的实现类似于上面的'MyActivity'示例。 –