工作流基础自定义分配活动

时间:2015-05-07 08:55:59

标签: workflow-foundation-4 workflow-foundation workflow-activity

我在我的设计师中定义了这个:

run

我认为如果我在那里添加分配但我错了,它会起作用。

    <sap:WorkflowItemPresenter>
       <statements:Assign DisplayName="Assign"/>
    </sap:WorkflowItemPresenter>

这是基类的代码。

我根本不需要改变Assign活动,我只想访问NativeActivityContext。实际上我正在尝试将其包装起来并对OnExecuteComplete方法中的上下文属性进行一些检查。有没有办法实现这个目标?

编辑1:

DotNetHitMan建议并在WF 4 Rehosted Designer - get foreach InArgument Value上向我展示如何使用这些跟踪,我确实成功地用他的解决方案解决了这个问题:

    [Browsable(false)]
    public Activity Body { get; set; }


    protected override void Execute(NativeActivityContext context)
    {
        ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete));
    }

    /// <summary>
    /// Called from Execute when Condition evaluates to true.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="instance">The instance.</param>
    public void OnExecuteComplete(NativeActivityContext context, ActivityInstance instance)
    {
        //to be added
    }

我仍然面对一些有点难看的东西。当检查Assign活动的参数时,我得到键&#34; Value&#34;。但是,如果我定义一个名为&#34; i&#34;并希望看到它的更改,因为这个Assign执行我必须看看VisualBasicReference&lt;&gt;检查在那里声明的变量的名称,就像在上面的代码中一样。这样做的方式确实有效,我设法覆盖整数和字符串现在很好..但是有没有可以在我的代码中使用的快捷方式?

编辑2 我今天得到了一个新想法并将其投入使用:

这是库代码:

                    if (trackingEventArgs.Activity is Assign)
                    {
                        Assign ass = trackingEventArgs.Activity as Assign;

                        if (ass.To.Expression != null)
                        {
                            dynamic vbr = null;

                            if ((ass.To.Expression is VisualBasicReference<int>))
                            {

                          //vbr.ExpressionText will hold the value set in the To section of the Assign activity, one of the variables will reside here

                                vbr = ass.To.Expression as VisualBasicReference<int>;
                            }
                            else if ((ass.To.Expression is VisualBasicReference<string>))
                            {
                                vbr = ass.To.Expression as VisualBasicReference<string>;
                            }

                            ActivityStateRecord activityStateRecord = null;

                            if (trackingEventArgs.Record != null)
                                activityStateRecord = trackingEventArgs.Record as ActivityStateRecord;


                            if (activityStateRecord != null)
                            {
                                if (activityStateRecord.Arguments.Count > 0)
                                {
                    //checking if the variable defined in the To section is to be displayed in the watch window   
                     GlobalFunctions.WatchWindowViewModel.VariableDefinition existingVariable = GlobalFunctions.WatchWindowViewModel.Instance.VariableExists(vbr.ExpressionText);

                                    if (existingVariable != null)
                                    {
                                        foreach (KeyValuePair<string, object> argument in activityStateRecord.Arguments)
                                        {
                                            if (argument.Key.Equals("Value"))
                                            {
                                                Application.Current.Dispatcher.Invoke(
                                                    () =>
                                                    {

                                                        existingVariable.VariableValue.Clear();
                                                        existingVariable.VariableValue.Add(
                                                            argument.Value.ToString());
                                                    });
                                            }
                                        }
                                    }
                                }

                            }
                        }
                    }

设计师:

public sealed class CustomAssign : NativeActivity, IActivityTemplateFactory
{
    [Browsable(false)]
    public Activity Body { get; set; }


    protected override void Execute(NativeActivityContext context)
    {
        ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete));
    }

    /// <summary>
    /// Called from Execute when Condition evaluates to true.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <param name="instance">The instance.</param>
    public void OnExecuteComplete(NativeActivityContext context, ActivityInstance instance)
    {
        //to be added
    }

    Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
    {
        return new CustomAssign
        {
            Body = new Assign()
        };
    }
}

所以,简而言之:我已经在我的自定义活动中托管了Assign活动并更改了ControlTemplate,以便只保留ContentPresenter,而ContentPresenter又是Assign。现在,通过将其拖动到设计器,您将拥有完全原始的外观,但能够编写代码并检查执行步骤:

<sap:ActivityDesigner x:Class="ARIASquibLibrary.Design.CustomAsignDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:statements="http://schemas.microsoft.com/netfx/2009/xaml/activities" Collapsible="False" BorderThickness="20" BorderBrush="Transparent">
<sap:ActivityDesigner.Template>
    <ControlTemplate TargetType="sap:ActivityDesigner">
        <Grid>
            <ContentPresenter HorizontalAlignment="Center"
                                      VerticalAlignment="Center"/>
        </Grid>
    </ControlTemplate>
</sap:ActivityDesigner.Template>
<DockPanel LastChildFill="True">
    <sap:WorkflowItemPresenter Item="{Binding Path=ModelItem.Body, Mode=TwoWay}"/>
</DockPanel>
</sap:ActivityDesigner>

 protected override void Execute(NativeActivityContext context)

为什么?通过context.DataContext,您可以获取此活动所在范围内的所有变量和参数,以便开发监视窗口。

1 个答案:

答案 0 :(得分:1)

不是处理每个变量类型,只需将表达式转换为其基接口。

ITextExpression vbr = ass.To.Expression as ITextExpression;

然后,您只需访问表达式文本属性,而无需关心分配给表达式的变量类型。

GlobalFunctions.WatchWindowViewModel.VariableDefinition existingVariable = GlobalFunctions.WatchWindowViewModel.Instance.VariableExists(vbr.ExpressionText);

这应该迎合(我希望)所有可以应用的变量类型。