Wednesday 14 September 2011

Workflow Wizards – Part 1

We are building an application using WPF, Prism and Windows Workflow Foundation (WF). The team had already defined the business processes as Visio flow charts and we wanted to use the new Flowchart workflows to implement them. This meant driving the user interface from the workflows.

This is the first in a series of posts to describe how one would implement a set of wizard pages that are driven by a Flowchart based workflow.

In implementing the user interface, we faced two major challenges:

  1. How would the workflow request user input and receive a result?
  2. How would the user indicate to go to the next step or the previous step?
  3. How would the implementer of the view model know what type of result to return?

The eventual solution to both of these were relatively simple, but it took us a while to get there. The solution consists of the following components:

  1. NavigationActivity: This is a base class for custom activities that will request interaction with the user. It inherits from NativeActivity.
  2. UserPrompt: A class that will be used to pass information from the user interface to the workflow. It also contains the name of a bookmark – more on this later.
  3. The actual flowchart workflow, that consists of built-in activities, WCF service calls and of course the activities derived from NavigationActivity to request information from the user.
  4. Workflow interface: Each workflow will have an interface that should be implemented by the view model. The interface defines the methods the activities will call when requesting user interaction. Each interface method will have at least one parameter: A UserPrompt.

      The workflow

      image

      This is part of our EditAccountHolder workflow. The CreditCheck activity is a custom, NavigationActivity derived activity. It prompts the user to perform a credit check and expects a result in the form of an attached file. Each navigation activity has a boolean result that indicates whether the user clicked Next or Previous. This is evaluated in the Decision Activity. If Next is selected, the workflow continues. If Previous is selected, we either move back to the previous user interaction, or set an overall result if we are already at the beginning of the workflow.

      Workflow interface

      The workflow’s interface looks like this:

      	public interface IEditAccountholder
      {
      /// <summary>
      /// Prompts the user to perform a credit check.
      /// </summary>
      /// <param name="userPrompt">Set <see cref="UserPrompt{T}.Result"/> to the credit check result</param>
      /// <param name="company">The company to perform the credit check for</param>
      void PerformCreditCheck(UserPrompt<CreditCheckResult> userPrompt, Company company);

      }

      User interaction


      The credit check activity calls IEditAccountHolder.PerformCreditCheck and then sets a bookmark to wait for the response. It is the view model’s responsibility to prompt the user for input and collect results. Once this is done, the results are stored in the UserPrompt and the workflow is resumed, passing the UserPrompt as the value parameter of ResumeBookmark.


      Conclusion


      It is not really obvious from the above how our three problems are solved. Part 2 will contain the code for UserPrompt and NavigationActivity which will hopefully answer your questions.


      No comments:

      Post a Comment