One of the major changes in Windows Workflow Foundation 4.0 is the Activity Designer. The new Activity Designer is based on WPF.
Introduction
Visual Studio 2010 released with workflow foundation 4.0. Workflow Foundation 4.0 is introduced a significant amount of change from the previous versions of the technology. The change varies from the core of the workflow foundation, runtime and tools. Workflow foundation 4.0 re-architected to improve the performance and productivity of the WF.
One of the major changes is in Activity Designer. The new Activity Designer is based on WPF [Windows Presentation Framework], which gives lot of flexibility to the developer. Creation of a custom look and feel using the new Activity Designer is very easy.
Activity Designer
Before starting with the new Activity Designer, let us create an Activity Designer Library. Create a project of type Activity Designer Library.
Right click on the solution and Add an Activity Designer item to the project.
Activity Designer will create two file; one .xaml file and another .xaml.cs file. Designer level customizations are mainly performed in .xaml file. We can do some customization like, when a property change, change the value of another property by tracking the designer events in .xaml.cs file. In this article, we will look into the customization using .xaml file only.
After adding the Activity Designer, add the custom activity class to the project. Following is the sample activity class derived from CodeActivity
[Designer(typeof(ActivityDesigner1))]
public class ActivityDesigner : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
throw new NotImplementedException();
}
}
The Designer attribute specified for the class bind the Activity with the specified Activity Designer. Build the Project and add the Custom Activity to either FlowChart or Sequential workflow.
The default design of the activity is as follows
Activity with an Icon
We will start our customization by changing the icon associated with the Activity Designer. Specify the Icon under the ActivityDesigner.Icon tab and draw the icon using ImageDrawing.
<sap:ActivityDesigner.Icon>
<DrawingBrush>
<DrawingBrush.Drawing>
<ImageDrawing>
<ImageDrawing.Rect>
<Rect Location="0,0" Size="16,16" ></Rect>
</ImageDrawing.Rect>
<ImageDrawing.ImageSource>
<BitmapImage UriSource="..\Resources\activityIcon.ico" ></BitmapImage>
</ImageDrawing.ImageSource>
</ImageDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</sap:ActivityDesigner.Icon>
The new Activity Designer with custom Icon will look like
Activity with one Child Activity
Let us move to the next step, where we will create an activity which holds another activity. Our custom activity will work as a container for another activity. For defining a custom activity as container, we can use the WorkflowItemPresenter defined in System.Activities.Presentation namespace.
Inside the activity designer, define the WorkflowItemPresenter as
<sap:WorkflowItemPresenter AllowDrop="True" Name="InsideItem" HintText="Drop Item here" Item="{Binding Path=ModelItem.Child}">
</sap:WorkflowItemPresenter>
Item attribute is bind to the child property of the corresponding Activity. Please refer the attached code for more details on the activity code.
Prefix sap is defined as below
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
When you drag the custom activity, it will look like
Drag any built-in or custom activity to the newly created custom activity. Here we dropped one WriteLine activity into our custom activity.
Activity with Multiple Child Activities
There are many scenarios where we need to execute a set of activities in a sequence. For defining a custom activity just like Sequence activity to hold a number of other activities, we can use the WorkflowItemsPresenter defined under System.Activities.Presentation.
Below code segment define the WorkflowItemsPresenter with vertical orientation. It uses one small rectangle to separate two activities. Also the child activities dropped on the WorkflowItemsPresenter is bind to the Activities property defined in the activity.
<sap:WorkflowItemsPresenter Items="{Binding Path=ModelItem.Activities}" HintText="Insert Activities Here">
<sap:WorkflowItemsPresenter.SpacerTemplate>
<DataTemplate>
<Rectangle Fill="#FF1F6F6F" Width="10" Height="10" />
</DataTemplate>
</sap:WorkflowItemsPresenter.SpacerTemplate>
<sap:WorkflowItemsPresenter.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</sap:WorkflowItemsPresenter.ItemsPanel>
</sap:WorkflowItemsPresenter>
When you drag the custom activity, it will look like
In the following example, we added two activities to our Custom activity; one Assign Activity and another WriteLine Activity.
Activity with User Control
As the activity designer is based on WPF, we can add any WPF user control to our activity.
We have a user control called WPFUserControl, which is included in the activity designer using the following code.
<local:WPFUserControl x:Name="customControl"></local:WPFUserControl>
For more details about the user control, please refer the attached code sample.
Now the activity designer will look like
Activity with Custom Look and Feel
Here, we are going to re-define the look and feel of the activity designer. In the following example, we defined a custom activity designer with rounded rectangle shape. Inside the custom activity, we placed one double Arrow and a TextBlock.
The main code used by the activity designer is as follows. Please refer the attached code sample for more details.
<ControlTemplate x:Key="CustomTemplate">
<Border x:Name="border" BorderThickness="1"
BorderBrush="#FF582222"
Background="{DynamicResource {x:Static SystemColors.InfoBrushKey}}"
CornerRadius="4" Focusable="True"
>
<Grid>
<Canvas Width="80" Height="30" HorizontalAlignment="Center" Margin="8,8,8,8">
<Polygon Points="4,20 14,0 14,10 94,10 94,0 104,20 94,40 94,30 14,30 14,40" Stroke="Black"
StrokeThickness="3" StrokeLineJoin="Round" HorizontalAlignment="Center"
VerticalAlignment="Center" Fill="#FF3C56AD"></Polygon>
</Canvas>
<TextBlock Text=" CustomActivity" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="#FFECEE5F" FontStretch="UltraCondensed" TextTrimming="CharacterEllipsis" FontWeight="Bold" />
</Grid>
</Border>
</ControlTemplate>
<sap:ActivityDesigner.Style>
<Style TargetType="{x:Type sap:ActivityDesigner}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ShowExpanded}" Value="false">
<Setter Property="Template" Value="{StaticResource CustomTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</sap:ActivityDesigner.Style>
The new custom activity designer will look like
Conclusion
Workflow Foundation 4.0 is giving the full flexibility to redefine the look and feel of a custom activity. You can define the activity to represent the functionality of the activity. This will make the custom activities more readable and understandable in the workflow. Also, the workflow design looks more readable and clear.