Introduction to XAML in Windows Workflow Foundation






4.82/5 (14 votes)
Apr 13, 2007
9 min read

145836

803
Third article in a Windows Workflow Foundation tutorial
Introduction
This is the third article in introductory series of articles on 'Windows Workflow Foundation'. In the first article we took at quick tour of Windows Workflow Foundation and also developed a rudimentary flight booking system which was based on 'sequential workflow'. Later on, we explored 'state-machine workflow' in the second article and developed a purchase ordering system. Now we will focus on XAML and learn how we can use it to design workflows in Windows Workflow Foundation.
Hello XAML!
Extensible Application Markup Language or XAML (pronounced zammel) is a new declarative language that is used in Windows Framework and Windows Presentation Foundation. Introduced with .NET Framework 3.0, XAML is harbinger of declarative (in contrast with imperative using coding) programming model. In Workflow Foundation, workflows can be created using code as well as XAML. Even fully XAML-based solutions are possible with no code at all! This not only gives flexibility of no-compilation-needed to applications, it also opens up a window of possibility for entirely non-technical persons (like business analysts) to design workflows. (Though Workflow Foundation is targeted for programmers, experiments are underway around the globe for making it feasible for business analysts to model processes in it).
XAML and Workflow Foundation
One can design workflow in three possible ways using Workflow Foundation; purely code based, partially code/XAML based, and totally XAML based. Partially code/XAML based workflows are combination of code and XAML. For instance, a typical scenario would be: a panoramic view of application is taken and workflow is defined using XAML, and later on, technical nitty-gritty is added by developer(s) for each workflow activity in code. These solutions need compilation. Purely XAML based solutions have workflow as well as all conditions/rules specified in XAML and can be hosted without compilation, though 'XAML Activation' would be needed to make them work.
What we are going to cover in this article
We will develop the world's simplest sequential workflow using XAML, add few rules 'declaratively' i.e. in XAML and then insert some code of displaying in console. We will learn a declarative programming model, play with XAML and see how integration of XAML and code can work!
Let's start the show
To all alpha blue geeks, I salute their patience for bearing all my theoretical musings till now, and invite them into venturing some real exciting practical work. Click on 'Microsoft Visual Studio 2005' in your Start menu, select 'Create New Project' and select 'Sequential Workflow Console Application'.
By default, Workflow Project includes code based workflow file, now since we would rather want to play with XAML, we will delete the file. Right-click project in 'Solutions Explorer', select 'Add New Item' and select 'Sequential Workflow with Code Separation' file. 'Code Separation' is an indicator that we are doing 'something exciting' (read: XAML) separate than crude code here.
That done, click on 'Add' and you would see standard empty workflow designer window. Hang here for a moment and let's explore what files are included in our pet project. In the 'Solution Explorer' window, there is MyWorkflow.xoml, this is the file that contains our XAML for workflow. Since workflow is empty right now, if you open-up the file, it would only have header node. [You can view XAML by right-clicking the file and selecting 'view in browser' or alternatively, go into the project folder, selecting MyWorkflow.xoml file and opening in your favorite XML editor.]. Here is how MyWorkflow.xoml should be look like currently.
<SequentialWorkflowActivity x:Class="FirstXAMLWFApplication.MyWorkflow 1"
Name="MyWorkflow 1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</SequentialWorkflowActivity>
Let's do a quick look at it with a magnifying glass. The root element is the 'Sequential Workflow Activity'; as it should be, since we are developing a sequential workflow application.
The other option is StateMachineWorkflowActivity. The element has two important attributes; Class and Name, where 'Class' specifies fully classified name of our workflow class, 'Name' is simply our workflow's 'name' property value.
To
quench our thirst for doing-something-exciting, let's add a While
activity in our
workflow. A While
activity is part of Microsoft's provided 'Base Activity
Library' which contains numerous activities that are used in a variety of
workflows, irrespective of which business domain they belong to. A few activities in the library
are: Code
, IfElse
, Delay
, WebServiceInput
, Replicator
etc.
The While
activity is
one of the simplest and mostly used. Almost every workflow has task(s) that
are needed to run in iteration; hence While
activity, where unless a particular
condition is fulfilled, the loop continues to run a specific activity.
We
can always add the While
activity by doing a drag-drop in the Workflow designer window, but
let's play with the cool and crude XAML first.
Open up MyWorkFlow.xoml and add the following code (shown in bold).
<SequentialWorkflowActivity
x:Class="FirstXAMLWFApplication. MyWorkflow" Name="MyWorkflow "
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<WhileActivity x:Name="whileActivity1">
</WhileActivity>
</SequentialWorkflowActivity>
Save the file and switch back to VS.NET IDE and open up workflow. It will look like:
Cool right!? But can you see that red exclamation sign? It is denoting the fact that we haven't specified any condition for the loop to terminate. Let's go into the code and add a protected variable in the workflow class. Code excerpt:
namespace FirstXAMLWFApplication
{
public partial class MyWorkflow : SequentialWorkflowActivity
{
public Int32 counter;
}
}
Go
back to the designer window and select 'Declarative Rule Condition' in the 'Condition'
property of the While
activity, then click on 'Ellipse' of 'Condition Name'. The following
dialog should display.
Click on 'Add' to go to the 'Rule Condition Editor' and add the following condition.
We
have added a simple condition here which will make the While
loop continue until
counter
reaches 10, where it will terminate. This is probably a good time to go
back to our XAML file and see how this declarative condition got added in it.
<SequentialWorkflowActivity x:Class="FirstXAMLWFApplication.MyWorkflow"
x:Name="MyWorkflow"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<WhileActivity x:Name="whileActivity1">
<WhileActivity.Condition>
<RuleConditionReference ConditionName="Condition1" />
</WhileActivity.Condition>
</WhileActivity>
</SequentialWorkflowActivity>
"Well,
I can see the condition property is set as Condition1
which was the name of our
recently added condition, but where is the actual condition statement?" Good
question! There is a separate file in a project named as MyWorkflow.rules, all
rules are kept in this file. For brevity's sake, I am not adding an excerpt
from the file (though you can always download it along with the attached code at the top of the article
to have a detailed look into it). For now, let it suffice that our declarative rule statement is present in the .rules file, while the condition
name goes into XAML. This again shows us the power of using XAML for designing workflows,
as I can add a million rules in my project and relate it with some particular
activity by adding a single line in XAML! And can even later edit/replace it by
simply changing the name of the condition and that's it!
That's
good enough for making the while activity execute, now let's add an activity within
this one. You can think of it as the loop's body. Here we will add an IfElse
activity and then a Code
activity for each IfElse
branch within the While
activity.
This time we will use power of VS IDE and simply drag-drop activities within
workflow designer. The final shape of workflow after the addition of these new
activities would be like:
As
we can see, the IfElse
activity has two branches. One is executed when the If
condition is true and the other when the else
condition is true. We will assign proper
conditions to each of branch, but for now let's have a look at our XAML file to
see how this change in workflow got translated in it.
<SequentialWorkflowActivity x:Class="FirstXAMLWFApplication.MyWorkflow"
x:Name="MyWorkflow" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<WhileActivity x:Name="whileActivity1">
<WhileActivity.Condition>
<RuleConditionReference ConditionName="Condition1"/>
</WhileActivity.Condition>
<IfElseActivity x:Name="ifElseActivity1">
<IfElseBranchActivity x:Name="ifElseBranchActivity1">
<CodeActivity x:Name="codeActivity1"
ExecuteCode="codeActivity1_ExecuteCode" />
</IfElseBranchActivity>
<IfElseBranchActivity x:Name="ifElseBranchActivity2">
<CodeActivity x:Name="codeActivity2"
ExecuteCode="codeActivity2_ExecuteCode" />
</IfElseBranchActivity>
</IfElseActivity>
</WhileActivity>
</SequentialWorkflowActivity>
Simple and structured? You bet it is! Bold statements shows our new IfElse
and Code
activities. Now we add simple conditions in each branch of the IfElse
activity. For keeping it simple, we will simply check if the counter is even or
odd, and on the basis of this condition check, send each control to each branch. We
will add these two rules and assign them to each branch using the same mechanism
(from the Properties window -> Select Condition -> Rule Condition Editor) as
we did for While
activity. Our condition for each branch will be:
this.counter
% 2 == 0 // for even
this.counter
% 2 != 0 // for odd
Finally, our 'Select Condition' looks like:
Hey! Didn't I say we will write some code? Yes I did, and it is time to do so. Select 'CodeActivity1', click on 'Generate Handlers' in the 'Properties' window and delve into its handler code. Add the following code in it. We have simply displayed on the console announcing this is an even number and incremented our counter variable.
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Hello! " + Convert.ToString(counter) +
" is an even number!");
counter++;
}
Similarly, add following code for 'CodeActivity2'.
private void codeActivity2_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Hello! " + Convert.ToString(counter) +
" is an odd number!");
counter++;
}
Yey! That's it. We have our complete workflow. Let's go through what we did.
- We added a while activity using XAML.
- We
added a condition in the while activity 'declaratively'. The condition simply
checks whether the
counter
field is less than 10 - We
then drag-dropped
IfElse
andCodeActivity
withinWhile
activity. - Proper
conditions were added in each branch of the
IfElse
activity to check whether its an even / odd number - Code
was added in the
Code
activity handler for display at console and incrementing thecounter
field.
Workflow runtime needs a host to run workflows. Our host will be a simple console application. Our project contains Progam.cs, here our workflow runtime will actually get started. A workflow instance is created, executed and then runtime gets closed. There is not much science here; pretty simple code generated by VS IDE for us:
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender,
WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflowRuntime.WorkflowTerminated += delegate(object sender,
WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(
typeof(FirstXAMLWFApplication.MyWorkflow));
instance.Start();
waitHandle.WaitOne();
Console.ReadKey();
}
}
A new
runtime object is created. Two event handlers are provided for 'Completed' and
'Terminated' statuses for Workflow. Then 'Create Workflow' is called to get an
instance of our workflow and 'Start' is called to launch it. The runtime engine
will execute our workflow asynchronously, therefore, we need to block our thread
on the AutoResetEvent
object and wait for workflow to complete (otherwise even
before we could see what's written on our console window, it will close and
the program will exit!). Now, using AutoResetEvent
means the thread will be blocked
until it is 'set' in complete event handler.
That is it, buddies. Click on 'Run' and watch the show. Well our output will not have much for our aesthetic senses, but it should give us good idea about what XAML is. Why and how to use it with Workflow Foundation.
Our output window looks like:
What more we can do with XAML in Workflow Foundation?
A lot! We can even design fully XAML-based workflows and we won't even need to compile them. That is, one can just design a workflow using XAML (any tool other than Visual Studio can also be used, after all it's all about creating/altering an XML-like document) and deploy it to run. 'XAML Activation' is used in place of compilation to launch the workflow. This was beyond scope of this article and we opted or a mid-way approach, of using both XAML and code (declarative and imperative programming model) as this is how workflows are vastly designed and implemented.
Where to find more
My favorite books/links remain same as was specified in my previous articles.
- Programming Workflow Foundation – Practical WF Techniques and Examples using XAML and C# by K. Scott Allen
- Official Home of Workflow Foundation in webspace
- K. Scott Allen's blog
- Essential Windows Workflow Framework by DharmaShukla, BobSchmidt.
- Google! – Search gazillions of articles/blog posts appearing in the techie world everyday.