在自定义 WPF 组件中通过 context.ScheduleActivity() 传递变量

Passing variable through context.ScheduleActivity() in custom WPF component

我在 Windows Workflow Custom Sequence Activity

的帮助下使用以下代码创建了一个 activity 来模仿 WPF 中的序列 activity
using System.Activities;
using System.Activities.Statements;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace Custom_Activities
{
    [Designer("System.Activities.Core.Presentation.SequenceDesigner, System.Activities.Core.Presentation")]
    public class Scoped_Activity_Scope : NativeActivity
    {
        private string TestVariable = "testing testing";
        private Sequence innerSequence = new Sequence();

        [Browsable(false)]
        public Collection<Activity> Activities
        {
            get 
            {
                return innerSequence.Activities;
            }
        }

        [Browsable(false)]
        public Collection<Variable> Variables
        {
            get
            {
                return innerSequence.Variables;
            }
        }

        protected override void CacheMetadata(NativeActivityMetadata metadata)
        {
            metadata.AddImplementationChild(innerSequence);
        }

        protected override void Execute(NativeActivityContext context)
        {
            System.Console.WriteLine("Scope Executing");
            context.ScheduleActivity(innerSequence);
        }

    }
}

我还在下面创建了第二个自定义 activity

using System.Activities;

namespace Custom_Activities
{
    public sealed class Scoped_Activity : Scoped_Activity_Template
    {
        protected override void Execute(CodeActivityContext context)
        {
            System.Console.WriteLine("Scope Activity Executing");
            //System.Console.WriteLine(testVariable);
        }
    }
}

当我运行代码如下

我得到了想要的输出

Scope Executing

Scope Activity Executing

我如何根据注释掉的代码行从 class Scoped_Activity_Scope 传递变量 testVariable 以便在 Scoped_Activity 中使用?

首先你为内部 activity 创建一个 属性:

public string TestVariable { get; set; }

然后您可以通过 Activities 集合访问 属性。

有2种情况需要更新TestVariable的值:1,当TestVariable改变时,和2,当你添加一个新的Scoped_Activity到[=17] =].

数字 1 很简单,每次更改 parent 的 TestVariable 时只需更改所有 Scoped_Activity.TestVariable。 2 号有点困难。您需要能够捕获每次从 UI 更改 Activities 时触发的 CollectionChanged 事件。这可以通过 activity 的设计者实现。我假设您可能已经为 activity.

编写了自定义设计器
public Scoped_Activity_Scope_Designer()
{
    InitializeComponent();
    this.Loaded += AddCollectionChangedHandler;
}

private void AddCollectionChangedHandler(object sender, RoutedEventArgs e)
{
    var ownactivities = 
        ModelItem.Properties[nameof(Scoped_Activity_Scope.Activities)].Collection;
    ownactivities.CollectionChanged += AddTestVariable;
}

AddTestVariable 中,只需更新 ownActivities 中每个 activity 的 TestVariable 属性,您需要再次检索它。


顺便说一句,您也可以通过调用 Parent 来访问 TestVariable,但是话又说回来,您仍然需要在 Scoped_Activity_Designer 内部执行此操作实际上可以访问 parent。但是,Scoped_Activity_Designer 不知道 TestVariable 何时更新,也不知道何时调用 execute 以检索最新值。使用 CollectionChanged 可能是最好的方法。

这就是您通过 parent:

访问 TestVariable 的方式
var dataContext = 
    Parent.GetValue(Scoped_Activity_Scope_Designer.DataContextProperty);
if (dataContext != null)
{
    var designer = (Scoped_Activity_Scope_Designer) dataContext;
    var scoped_activity_scope = (Scoped_Activity_Scope) designer.ModelItem.GetCurrentValue();
    var scoped_activity = (Scoped_Activity) ModelItem.GetCurrentValue();
    scoped_activity.TestVariable = scoped_activity_scope.TestVariable;
}

您应该将此代码放在 Scoped_Activity_Designer 内的 Loaded 事件的处理程序中。

Scoped_Activity_Scope 中的 Execute 方法中,我添加了以下代码以遍历 innerSequence

中的活动
foreach(Activity a in innerSequence.Activities)
{
    if (a.GetType().IsSubclassOf(typeof(UiPath_Activities_Templates.Scoped_Activity_Template)))
    {
        Scoped_Activity_Template vet = null;
        vet = (Scoped_Activity_Template) a;
        vet.UpdateTestVariable("changed");
    }
}

并且在 class 'Scoped_Activity_Template' 中 'Scoped_Activity' 继承自(这个 class 之前是空的)我添加了以下代码

public static string TestVariable = "testing";

public void UpdateTestVariable(string newValue)
{
    TestVariable = newValue;
}

这样继承的 class Scoped_Activity 就可以访问变量 TestVariable.

当循环遍历 innerSequence 中的活动时,它会检查它是否继承自 Scoped_Activity_Template,它会调用方法 UpdateTestVariable 来更新变量。

然后执行 class Scoped_Activity 时,它将具有更新的变量。