Windows Workflow Foundation – Getting Started Setup: Install .NET 3.0 Framework On line: http://www.microsoft.com/downloads/details.aspx?familyid=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en Install Visual Studio 2005 Extensions for Windows Workflow At the bank: I:\Software\Microsoft\MS Visual Studio\Visual Studio Plugins and Extensions\WF Visual Studio 2005 Plugin\Visual Studio 2005 Extensions for Windows Workflow Foundation (EN).zip On line: http://www.microsoft.com/downloads/details.aspx?familyid=5D61409E-1FA3-48CF-8023-E8F38E709BA6&displaylang=en Source information: Windows Workflow Foundation Essentials: http://www.code-magazine.com/Article.aspx?quickid=0711071 or http://www.devx.com/codemag/Article/36317 dnrTV: • Windows Workflow Foundation (1 of 4): http://www.dnrtv.com/default.aspx?showNum=21 • Windows Workflow Foundation (2 of 4): http://www.dnrtv.com/default.aspx?showNum=22 • Windows Workflow Foundation (3 of 4): http://www.dnrtv.com/default.aspx?showNum=23 • Windows Workflow Foundation (4 of 4): http://www.dnrtv.com/default.aspx?showNum=24 • Workflow Rules Engine: http://www.dnrtv.com/default.aspx?showNum=90 • The Marriage of WF and WCF: http://www.dnrtv.com/default.aspx?showNum=103 Windows Workflow Foundation Tutorials (these are OK, but they create everything from code instead of using the Visual Studio IDE which makes it a little confusing): http://msdn2.microsoft.com/en-us/library/ms735927(VS.85).aspx • Create a Sequential Workflow • Create a State Machine Workflow • Create a Custom Activity • Host the Windows Workflow Foundation Runtime • Use Rules and Conditions Console Workflow Application: Best way to get your feet wet is following the Windows Workflow Foundation Essentials article in CoDe Magazine listed above in Source information. The idea of Activity-Oriented programming, along with creating custom Activities, the use of “dependency properties”, and the concept of “activity data binding” are all introduced. One difference I would add is to create the custom Activities in their own project. Select New > Project. In the New Project dialog for Project types, expand Visual C# and highlight Workflow. In the Templates pane on the right, select Workflow Activity Library. Change the Name, set the Location, and click OK. The second difference I would add is to create the Workflow in its own project. Select New > Project. In the New Project dialog for Project types, expand Visual C# and highlight Workflow. In the Templates pane on the right, select Sequential Workflow Library. Change the Name, set the Location, and click OK. Make sure to add a reference to your new Workflow Activity Library from your Sequential Workflow Library and add a reference to your new Sequential Workflow Library from your Sequential Workflow Console Application. Custom Activities – a best practice that allows the code within an Activity to be reusable. Creating a Code activity (instead of a custom Activity) ties the event handler directly to the workflow diagram. When added, you will usually want to change the Base Class the Activity is based on by clicking the Activity’s Base Class property ellipses and opening the dialog. In the left pane select System.Workflow.ComponentModel, in the right pane select Activity, then click OK. Dependency properties are used to propagate values between the Activity and the Workflow or other Activities. This is known as activity data binding. This feature helps create encapsulated Activities – because they only read and write to their own properties and don’t directly access the Workflow or other Activities (and therefore don’t have a string dependency on them) – making the Activity reusable in multiple Workflows. Once compiled, the custom Activities show up in the Toolbar for use within a Workflow. Override the Execute() method and add the custom code required to accomplish the task required of the Activity. Dependency properties – trick in creating them is to use code snippets. Right-click where you want to add the code, select Insert Snippet, double-click Workflow, double-click DependencyProperty – Property and the code template gets added. Type in the Property name and press the Tab key. Type in the Property data type and press the Tab key. Type in the Property description and press the Tab key. Type in the Property category (like Custom Property) and press Enter. These will get added to both Activities and the Workflow itself. Activity Data Binding – once dependency properties have been added to both the Workflow and Activities most of the work is done. Drag an Activity to the Workflow. The idea is to “bind” the Activity’s property to the Workflow’s property. Hover over the Activity property’s icon (in the Properties window) with the mouse and the tool tip “Bind Property” will display indicating that there are dependency properties that can participate in activity data binding. Click the Activity property’s associated ellipses button to display the Workflow’s (and other Activity’s) dependency properties. Select the appropriate property and click OK. Calling and executing the Workflow (AutoResetEvent is required for addressing multithreading issues within the Console application, but is NOT used when hosted within a WinForm application): class Program { static AutoResetEvent waitHandle = new AutoResetEvent(false); static void Main(string[] args) { using (WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { workflowRuntime.WorkflowCompleted += new EventHandler(workflowRuntime_WorkflowCompleted); workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(SequentialWorkflowConsole.MyWorkflowProcess)); instance.Start(); waitHandle.WaitOne(); //Code added to "pause" and wait for input Console.WriteLine("Press any key to continue..."); Console.ReadLine(); } } } Passing Parameters to the Workflow: Need to use a Dictionary object: Dictionary parameters = new Dictionary(); Now add parameters to the Dictionary object: parameters.Add("PropertyName", propertyValue); Pass in the Dictionary object when creating the WorkflowInstance: WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(SequentialWorkflowConsole.MyWorkflowProcess), parameters); Obtaining Workflow Output – it will come off of some event either custom or standard as part of the EventArgs. Don’t forget to cast the OutputParameters appropriately since they all objects: static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e) { Console.WriteLine(e.OutputParameters["OrderCategory"]); waitHandle.Set(); } Winform Workflow Application: Based on best practices, I would create the custom Activities in their own project. Either add the existing project or select New > Project. In the New Project dialog for Project types, expand Visual C# and highlight Workflow. In the Templates pane on the right, select Workflow Activity Library. Change the Name, set the Location, and click OK. Additionally, I would create the Workflow in its own project. Either add an existing project or select New > Project. In the New Project dialog for Project types, expand Visual C# and highlight Workflow. In the Templates pane on the right, select Sequential Workflow Library. Change the Name, set the Location, and click OK. Make sure to add a reference to the Workflow Activity Library from your Sequential Workflow Library and add a reference to the Sequential Workflow Library from your WinForm Application. You also need to add references to System.Workflow.Activities, System.Workflow.ComponentModel, and System.Workflow.Runtime from your WinForm Application. Calling and executing the Workflow: Add a private variable to the WorkflowRuntime within your form: private WorkflowRuntime messageWorkflowRuntime = null; Create the Runtime and Instance the same way as in the Console Application (including passing parameters), but don’t include the AutoResetEvent / waitHandle: messageWorkflowRuntime = new WorkflowRuntime(); messageWorkflowRuntime.StartRuntime(); messageWorkflowRuntime.WorkflowCompleted += new EventHandler(workflowRuntime_WorkflowCompleted); messageWorkflowRuntime.WorkflowTerminated += delegate(object senderWF, WorkflowTerminatedEventArgs eWF) { Console.WriteLine(eWF.Exception.Message); }; // Construct workflow parameters Dictionary parameters = new Dictionary(); parameters.Add("PropertyName ", propertyValue); // Start the workflow WorkflowInstance messageWorkflowInstance = messageWorkflowRuntime.CreateWorkflow(typeof(SequentialWorkflowLibrary.MyWorkflowProcess), parameters); messageWorkflowInstance.Start(); Obtaining Workflow Output – it will come off of some event either custom or standard as part of the EventArgs. Don’t forget to cast the OutputParameters appropriately since they are all objects. Don’t forget to use InvokeRequired and Invoke() when addressing updating of the form – the event coming back from the Workflow is off a different thread: static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e) { if (this.lblOrderCategory.InvokeRequired) { this.lblOrderCategory.Invoke(new EventHandler(this.workflowRuntime_WorkflowCompleted), sender, e); } else { this.lblOrderCategory.Text = e.OutputParameters["OrderCategory"]; } } Adding a Workflow directly to the WinForm Application: Not a best practice; however, it can be done. Need to modify the WinForm Application .csproj file using NotePad. Add the following node within the first node (immediately after the node): {14822709-B5A1-4724-98CA-57A101D1B079};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} Add the following node near the bottom of the file after any other nodes that might be there: