Activity Binding in Windows Workflow Foundation

Windows Workflow Foundation provides a visual interface for creating and hosting workflows that integrate seamlessly into line-of-business applications built on the .NET 3.0 Framework. Activity binding, one feature of Windows Workflow Foundation, allows an activity author to expose the properties of his or her activity to other activities at a workflow level. Once the properties are available at the workflow level, they can interact with the components that serve as the solution’s user interface. This allows developers to set activity properties dynamically in a way that they are familiar with in a Visual Studio environment. This article walks through an example solution that demonstrates activity binding.

Why Use Activity Binding?

Workflows provide a means to perform functions behind the scenes. Take, for example, a solution that interacts with a user through an interface and asks for a social security number. The workflow component of this solution has two activities: One retrieves contact information for the employee, and the other retrieves the employee’s pay information. The question, then, is how does the solution propagate the social security number entered by the user to the activities that require the information to perform their functions? The answer is activity binding. (The code example in the following sections will show how to accomplish this.)

Activity binding also allows the solution to relay the social security number entered by the user to both activities while requiring the user to enter the number only once. This kind of reuse is a core concept in efficient, user-, and developer-friendly applications. The solution also could use activity binding in an activity-to-activity context, allowing one activity to synchronize a value with one supplied by another activity. Activity binding is, therefore, the glue between components in Windows Workflow.

Creating a Custom Activity

The first step in creating the example solution is to create a simple custom activity. In Visual Studio 2005, start a new solution with a Workflow Activity Library project. Visual Studio will provide a base activity (Activity1). Rename the activity to something suitable. The example in this article uses “GreetingActivity.” The GreetingActivity will be responsible for greeting a user with his or her first and last name; therefore, the activity needs two dependency properties: FirstName and LastName. Dependency properties are properties that are exposed to the properties window in Visual Studio, allowing easy, visual configuration. (Dependency properties fall outside the scope of this article. For more information, please see MSDN.)

To configure FirstName and LastName, open the code-behind for the custom activity. Visual Studio again comes to the rescue. To create a dependency property, insert a Workflow, Dependency Property code snippet. Name it, set its type, provide a description that will be presented in the property window, and place it in a category. For this example, the two dependency properties are configured as follows:

namespace MyActivityLibrary
{
   public partial class GreetingActivity: SequenceActivity
   {
      public static DependencyProperty FirstNameProperty =
         System.Workflow.ComponentModel.DependencyProperty.
         Register("FirstName", typeof(string),
         typeof(GreetingActivity));

      [Description("The First Name of the User")]
      [Category("Dependency Properties")]
      [Browsable(true)]
      [DesignerSerializationVisibility
         (DesignerSerializationVisibility.Visible)]
      public string FirstName
      {
         get
         {
            return ((string)(base.GetValue
               (GreetingActivity.FirstNameProperty)));
         }
         set
         {
            base.SetValue(GreetingActivity.FirstNameProperty, value);
         }
      }

      public static DependencyProperty LastNameProperty =
         System.Workflow.ComponentModel.DependencyProperty.
         Register("LastName", typeof(string),
         typeof(GreetingActivity));

      [Description("The Last Name of the User")]
      [Category("Dependency Properties")]
      [Browsable(true)]
      [DesignerSerializationVisibility
         (DesignerSerializationVisibility.Visible)]
      public string LastName
      {
         get
         {
            return ((string)(base.GetValue
               (GreetingActivity.LastNameProperty)));
         }
         set
         {
            base.SetValue(GreetingActivity.LastNameProperty, value);
         }
      }

Now that the dependency properties have been defined, it is time to define the activity’s function. This is done by overriding the Execute method of the activity. Simply add the following code:

protected override ActivityExecutionStatus Execute
   (ActivityExecutionContext executionContext)
{
   Console.WriteLine("Hello, " + FirstName + " " + LastName);
   return base.Execute(executionContext);
}

Now, the activity is ready to be consumed by a workflow.

Creating a Workflow to Consume a Custom Activity

Next, you add a new Sequential Workflow Console Application project to the solution. The GreetingActivity will be available in the Toolbox, and you now can drag it to the new workflow. The dependency properties you defined are displayed in the properties window for the activity in the workflow (see Figure 1).

Figure 1: Dependency Properties Displayed In Properties Window

This is very useful for workflow designers who wish to configure the properties of a custom activity in the visual designer. This can make your custom workflow appear professional and integrate flawlessly with the built-in activities of Windows Workflow Foundation.

However, you can expose these properties at the workflow level, offering additional flexibility and functionality to your applications. You can accomplish this in two ways: a code-driven method for the codeslingers and a visual method for those who prefer configuration in Visual Studio. The first is adding the properties manually to the workflow code-behind and then binding them to the activity properties with the designer. To do this, add the following properties (named WorkflowFirstName and WorkflowLastName to distinguish them from the properties defined at the activity level) to the code-behind:

private string workflowFirstName;

public string WorkflowFirstName
{
   get { return workflowFirstName; }
   set { workflowFirstName = value; }
}

private string workflowFirstName;

public string WorkflowLastName
{
   get { return WorkflowLastName; }
   set { WorkflowLastName = value; }
}

Now, return to the designer. In the properties window for the activity, click the ellipsis in the text box for the FirstName property. Choose the “Bind to an existing member” tab of the dialog and select the WorkflowFirstName property you just defined (see Figure 2).

Figure 2: WorkflowFirstName Property in “Bind to an existing member” Tab

This associates the value of the WorkflowFirstName property you can access from within the console application with the value of the activity’s property. Do the same thing with the LastName property, this time associating it with WorkflowLastName.

For those who find manually typing out property code too strenuous, you can let the designer do all of the work. Instead of switching to the code-behind, stay in the designer and click the FirstName ellipsis in the activity’s property window. This time, choose the “Bind to a new member” tab. Type in “WorkflowFirstName” as the name and choose Create Property (see Figure 3). Do the same for LastName, binding it to a new property named “WorkflowLastName”.

Figure 3: Type in “WorkflowFirstName” and Choose Create Property

The designer adds two dependency properties to the code-behind for you. They will accomplish the same thing as properties added manually, and it binds them to the activity properties.

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read