Share via


How to Programmatically Add a Workflow Variable when Rehosting the Workflow Designer

When creating workflows programmatically, variables can be added to an activity by adding them to the activity's variable collection, like this.

Variable<int> n = new  Variable<int>("n", 1);
Sequence s = GetSequenceActivityFromSomewhere();
s.Variables.Add(n);

If your application rehosts the workflow designer, you can't use that same approach to programmatically add a variable to an activity in the designer. If you do, a NullReferenceException will be thrown the next time the Variables pane is displayed in the rehosted designer. The following code examples appears to work when your un it, but the next time the Variables pane is opened a NullReferenceException is thrown.

// In this snippet, wd is a reference to the WorkflowDesigner instance.
// You can get a reference to the root Sequence activity in the rehosted
// designer by using the ModelService.
ModelService modelService = this.wd.Context.Services.GetService<ModelService>();
Activity a = modelService.Root.GetCurrentValue() as  Activity;
Sequence s = a as  Sequence;
Variable<int> n = new  Variable<int>("n");
n.Default = 1;
s.Variables.Add(n);

In order to successfully add a variable programmatically, you must get the ModelItem that represents the root item of the workflow, and add the variable to its variables collection. This is demonstrated in the following example.

// In this example the root activity is a Sequence. If it was not a Sequence, or you wanted
// only to ensure that the activity had a Variables collection, you could check
// to ensure that mi.Properties.Find("Variables") did not return null.
ModelService modelService = this.wd.Context.Services.GetService<ModelService>();
ModelItem mi = modelService.Root;
if (mi.ItemType.Equals(typeof(Sequence)))
{
    Variable<int> n = new  Variable<int>("n");
    n.Default = 1;
    mi.Properties["Variables"].Collection.Add(n);
}

Testing the Sample Code

To try this out, open the Designer ReHosting sample. Open the RehostingWFDesigner.xaml.cs file and add a member variable to the RehostingWfDesigner class:

WorkflowDesigner wd;

Change the line in OnInitialized that creates a new instance of the Workflow designer to use the WorkflowDesigner member variable instead of declaring a local variable.

// create the workflow designer
// Use the newly created wd member variable
// WorkflowDesigner wd = new WorkflowDesigner();
wd = new  WorkflowDesigner();

Add a button to the form, and use the previous code snippets. Click the button to run the code, and then click the Variables button on the workflow designer to display the Variables pane. When using the code from the first example, a NullReferenceException is thrown. When using the code from the second example, a new variable is successfully added and is displayed in the Variables pane.