Tuesday, 19 October 2010

Workflow 4.0 Activity Designer

In this post i'm going to explain how to make a custom activity better visually. 
First of all I have a custom code activity called RequestManagerAction. It inherits from CodeActivity and overrides its Execute method. (I may do a post on code activities later).

The visual representation of code activity, by default, looks like this:
And by the end of this post it will look like this:
The first step is to create a new peoject for your activity designer. As we want to "design" RequestManagerAction I have created a new project called: RequestManagerActionDesignerLibrary. And inside this I add a new Activity Designer Item from the Workflow - installed templates called RequestManagerActionDesigner.xaml.

the initial view after opening RequestManagerActionDesigner.xaml is a split screen with the Xaml that represents the design in the bottom part of the screen and the actualy visual design in the top part.

In the bottom pane we can see the Xaml. First of all I want to set the Collapsible property to false as I don't want my designer to be collapsible. 

The 2nd taks is to add an ArgumentToExpressionConverter to my Xaml. This defines the mapping between arguments and expressions and provides the functionality to convert between these objects. Typically, this converter is used declaratively when using an ExpressionTextBox in a custom activity designer.

The next thing I want to do it sort out my layout. As my custom activity has 3 properties:

The main aim of what we are doing here is to show ExpressionTextBoxes for all 3 of these.
I will add a grid of 2 columns and 3 rows for our properties.

You can see that inside this grid we have some (3) collapsed TextBlock sections. I will explain these now.

Each TextBlock is for a property.
The first TextBlock is for the ExpenseRequest property of our custom activity:
You can see the obvious items marked out in the above picture.Note that the position inside the grid defined above is set by the Grid.Row and Grid.Column indexes which are zero(0) based.
You can also see that our expression text box is bound to ModelItem.SubmitExpenseRequest.

SubmitExpenseRequest is a class in my Contracts project that is part of my domain model:

The ModelItem represents the activity that that the designer is currently editing. This object sits between the visual elements that present an activity to the developer and the in-memory representation of the activity.

You can now see that we are well on the way to building our custom design:

I will now go ahead and add the other 2 ExpressionTextBoxes and the relevant properties.

You will notice the little smiley icon in the top left of the designer. To add this, I added the following xaml:

Now I am ready to associate my designer with the actual code activity that is already part of my workflow. If you remember it currently looks like this:
First I will add a reference to the project that my code activity is part of:

Once its referenced we can add an attribute to the top of our codeActivity class (Don't forget the System.ComponentModel import at the top!):

Once you have built the projects you will see the "RequestManagerAction" code activity in the toolbox. Drag this onto your workflow surface if it's not already there and you will see that the look of the activity is not just a small yellow box any more. Nice!! 

This is obviously more useful as we don't need to  use the properties pane to set the properties for our code activity, we can just type them straight into the workflow.