2
votes

Assume that I have a workflow with 3 Custom Activities which are placed in a Sequence Activity. And I created a Boolean variable (name it as “FinalResult”) at Sequence Activity level (Root) to hold the Result. My Intention is, I want to assign each Custom Activity Result to Root level variable (“FinalResult”) within the Custom Activity Execute method after finishing the activity.

I can get this by declaring the output argument in Custom Activity and placing the variable name at design time in the properties window of activity manually while designing the policy.

But I don’t want to do this by the end user. I want just the end user drag and drop the activities and write conditions on the” FinalResult” variable. Internally I have to maintain the Activity Result in “FinalResult” Variable through programmatically.

Finally I want to maintain the workflow state in “FinalResult” variable and access it anytime and anywhere in the workflow.

I tried like this below getting error "Property does not exist".

    WorkflowDataContext dataContext = context.DataContext;
    PropertyDescriptorCollection propertyDescriptorCollection = dataContext.GetProperties();
    foreach (PropertyDescriptor propertyDesc in propertyDescriptorCollection)
    {
        if (propertyDesc.Name == "FinalResult")
             {
                 object data = propertyDesc.GetValue(dataContext);// as WorkUnitSchema;
                 propertyDesc.SetValue(dataContext, "anil");
                 break;
             }
    }

Please let us know the possible solutions for the same.

1

1 Answers

0
votes

I do this all the time.

Simply implement IActivityTemplateFactory in your activity. When dragged and dropped onto the design surface, the designer will determine if your activity (or whatever is being dropped) implements this interface. If it does, it will construct an instance and call the Create method.

Within this method you can 1) instantiate your Activity and 2) configure it. Part of configuring it is binding your Activities' properties to other Activities' arguments and/or variables within the workflow.

There are a few ways to do this. Most simply, require these arguments/variables have well known names. In this case, you can simply bind to them via

return new MyActivity
{
    MyInArgument = new VisualBasicValue<object>(MyActivity.MyInArgumentDefaultName),
};

where MyActivity.MyInArgumentDefaultName is the name of the argument or variable you are binding to.

Alternatively, if that variable/argument is named by the user... you're in for a world of hurt. Essentially, you have to

  1. Cast the DependencyObject target passed to the Create method to an ActivityDesigner
  2. Get the ModelItem from that AD
  3. Walk up the ModelItem tree until you find the argument/value of the proper type
  4. Use its name to create your VisualBasicValue

Walking up the ModelItem tree is super duper hard. Its kind of like reflecting up an object graph, but worse. You can expect, if you must do this, that you'll have to fully learn how the ModelItem works, and do lots of debugging (write everything down--hell, video it) in order to see how you must travel up the graph, what types you encounter along the way, and how to get their "names" (hint--it often isn't the Name property on the ModelItem!). I've had to develop a lot of custom code to walk the ModelItem tree looking for args/vars in order to implement a drag-drop-forget user experience. Its not fun, and its not perfect. And I can't release that code, sorry.