WF 工作流 设计器 小问题 ForEach ParallelForEach


在参考了下面2个博主的文章后

 

 

http://www.cnblogs.com/zhuqil/archive/2010/01/13/Workflow-Designer.html 

 

http://www.cnblogs.com/foundation/archive/2010/02/25/1673837.html

 

 

自己也学着做了一个 但是在保存 ForEach 的时候 xaml 不能正常保存

 

认真Google之后  找到一篇解释的文章

http://blogs.msdn.com/b/tilovell/archive/2009/12/29/the-trouble-with-system-activities-foreach-and-parallelforeach.aspx

 

The Trouble with System.Activities.ForEach (and ParallelForEach)

 

 

Another forum post reminded me of one thing about ActivityAction that throws me for a loop every time. Every time, that is, that I'm rehosting workflow designer or creating new custom activities, so maybe not that often but it's kind of annoying.

Imagine, here's us, creating a toolbox for our rehosted application:

   using System.Activities.Statements;

   using System.Activities.Presentation.Toolbox;

   ... 

 

   toolbox.Categories.Add(

       new System.Activities.Presentation.Toolbox.ToolboxCategory

       {

           CategoryName = "Trouble",

           Tools = {

               new ToolboxItemWrapper(typeof(ForEach<>)),

               new ToolboxItemWrapper(typeof(ParallelForEach<>))

           }

       }

    );

 

Which looks fine, right? It appears to work. We can drag and drop to create a ForEach<T> activity into our workflow. We can even apparently drag and drop a flowchart, for example, inside the ForEach. We can continue happily for quite a while until suddenly we notice: there is something really weird going on here.

 

When we save to XAML, the flowchart we added inside the ForEach isn't saved. If we double-click the flowchart, we end up in a breadcrumb view of the flowchart, but with no parent view to go back to! Somehow our flowchart has become disconnected from the rest of the workflow. At this point I went crazy wondering: is it a bug with ForEach activity? No, it works just perfectly in Visual Studio. Why?

 

Hint:

Look at the XAML serialization for a typical ForEach activity (created in VS, of course):

 

<ForEach x:TypeArguments="x:Int32" Values="[{1, 2, 3, 4}]">

  <ActivityAction x:TypeArguments="x:Int32">

    <ActivityAction.Argument>

      <DelegateInArgument x:TypeArguments="x:Int32" Name="item" />

    </ActivityAction.Argument>

    <WriteLine Text="Can I have a little more" />

  </ActivityAction>

</ForEach>

Bigger hint:

Now here is a ForEach activity from our rehosted application which didn't serialize its contents properly at all:

<ForEach x:TypeArguments="x:Int32" Values="[{1, 2, 3, 4}]"/>

So there is no ActivityAction. [What's ActivityAction? Here's the lowdown from Matt.]

So, how does that explain what is going on? To understand why the flowchart appeared to be added even though there was no ActivityAction to add it to, understand the problem is that the WPF binding in the Activity Designer for ForEach is silently failing. Here are two interesting controls on the ForEach designer

<TextBox Text="{Binding Path=ModelItem.Body.Argument.Name, Mode=TwoWay, ValidatesOnExceptions=True}" />

 

<sap:WorkflowItemPresenter IsDefaultContainer="True"

                  HintText="{DynamicResource dropActivityHint}"

                  Item="{Binding Path=ModelItem.Body.Handler, Mode=TwoWay}"

                  AllowedItemType="{x:Type sa:Activity}" />

(There is also one more control, an ExpressionTextBox.)

The first control is the TextBox where we declare the name of the ForEach activity's 'loop variable' (such as 'i'). The second control is the holder for the child activity we drag and drop: flowchart. When we drag and drop, the binding Binding Path=ModelItem.Body.Handler fails to evaluate, because ModelItem.Body is null. But the visual of course doesn't fail to update, which makes us think everything is fine even though it's really not.

OK, so now we know the problem how can we fix it? Well, we could fix our app by writing an IActivityTemplateFactory like this:

public class ForEachFactory<T> : IActivityTemplateFactory

{

    public Activity Create(DependencyObject target)

    {

        return new ForEach<T>

        {

            DisplayName = "ForEachFromFactory",

            Body = new ActivityAction<T>

            {

                Argument = new DelegateInArgument<T>("i")

            }

        };

    }

}

and add that to our toolbox instead (... new ToolboxItemWrapper(typeof(ForEachFactory))). Or, now that we understand that, we could be a little bit lazier:

new ToolboxItemWrapper(typeof(System.Activities.Core.Presentation.Factories.ForEachWithBodyFactory<string>));

 

new ToolboxItemWrapper(typeof(System.Activities.Core.Presentation.Factories.ParallelForEachWithBodyFactory<>))

Yep, these classes exist in the framework already. Note, they are in a different assembly. System.Activities.Core.Presentation, not System.Activities.

 

 

转载于:https://www.cnblogs.com/gameoverboss/archive/2010/05/31/1747992.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值