Task 2: Create the HandleExternalEvent Activities

Download sample

At this point, the workflow has done the following:

  • Received one parameter from the host application.

  • Evaluated the Amount parameter to determine which party is responsible for approving or rejecting the expense report.

  • Notified the host application that approval is needed before it continues.

In this task, you use the ListenActivity activity, together with the HandleExternalEventActivity activities, to listen for specific events that the host application raises. When an approval or rejection event is raised, the workflow continues, sets the result, and then finishes.

Each branch of a ListenActivity activity is an EventDrivenActivity. The first activity of the composite EventDrivenActivity must be an activity that implements the IEventActivity interface. The HandleExternalEventActivity activity is used in each EventDrivenActivity branch of the ListenActivity to listen for the ExpenseReportApproved event or the ExpenseReportRejected event raised by the host application.

Note

Although you are encouraged to follow the exercises in a linear manner, it is not required. You can start on this exercise by opening the sample solution and proceeding to the steps in the following procedure.

Modifying the ExpenseReportWorkflow

In this step, you must modify the workflow so that it can listen for specific events that the host application raises.

To modify the ExpenseReportWorkflow

  1. In the ExpenseReportWorkflow class, create a new method named approveEvent_Invoked that accepts a Object named sender and an ExternalDataEventArgs named e as parameters.

  2. In the approveEvent_Invoked method, set the reportResult member field equal to the string value "Report Approved".

    void approveEvent_Invoked(object sender, ExternalDataEventArgs e)
    {
        this.reportResult = "Report Approved";
    }
    
  3. In the ExpenseReportWorkflow class, create a new method named rejectEvent_Invoked that accepts a Object named sender and an ExternalDataEventArgs named e as parameters.

  4. In the rejectEvent_Invoked method, set the reportResult member field equal to the string value "Report Rejected".

    private void rejectEvent_Invoked(object sender, ExternalDataEventArgs e)
    {
        this.reportResult = "Report Rejected";
    }
    
  5. In the ExpenseReportWorkflow class, create the following private fields.

    Type Name

    ListenActivity

    listenApproveReject

    EventDrivenActivity

    eventDriven1

    EventDrivenActivity

    eventDriven2

    HandleExternalEventActivity

    approveEvent

    HandleExternalEventActivity

    rejectEvent

    private ListenActivity listenApproveReject;
    private EventDrivenActivity eventDriven1;
    private EventDrivenActivity eventDriven2;
    private HandleExternalEventActivity approveEvent;
    private HandleExternalEventActivity rejectEvent;
    
  6. In the InitializeComponent method, create an instance of each field that is declared in the previous step.

    This must be done after the line that sets the CanModifyActivities to true.

    this.eventDriven1 = new EventDrivenActivity();
    this.eventDriven2 = new EventDrivenActivity();
    this.listenApproveReject = new ListenActivity();
    this.approveEvent = new HandleExternalEventActivity();
    this.rejectEvent = new HandleExternalEventActivity();
    
  7. Following the line that set the ParameterBindings of the invokeGetManagerApproval object in the InitializeComponent method, add the approveEvent object to the Activities collection of the eventDriven1 object by using the Add method, and passing the approveEvent object as a parameter to that method.

  8. Set the Name property of the eventDriven1 object to the value "eventDriven1".

    this.eventDriven1.Activities.Add(this.approveEvent);
    this.eventDriven1.Name = "eventDriven1";
    
  9. Add the rejectEvent object to the Activities collection of the eventDriven2 object by using the Add method and passing the rejectEvent object as a parameter to that method.

  10. Set the Name property of the eventDriven2 object to the value "eventDriven2".

    this.eventDriven2.Activities.Add(this.rejectEvent);
    this.eventDriven2.Name = "eventDriven2";
    
  11. Add the eventDriven1 object to the Activities collection of the listenApproveReject object by using the Add method, and passing the eventDriven1 object as a parameter to that method.

  12. Add the eventDriven2 object to the Activities collection of the listenApproveReject object by using the Add method, and passing the eventDriven2 object as a parameter to that method.

  13. Set the Name property of the listenApproveReject object to the value "listenApproveReject".

    this.listenApproveReject.Activities.Add(this.eventDriven1);
    this.listenApproveReject.Activities.Add(this.eventDriven2);
    this.listenApproveReject.Name = "listenApproveReject";
    
  14. Set the EventName property for the approveEvent object to the value "ExpenseReportApproved".

  15. Set the InterfaceType property of the approveEvent object to the System.Type of the IExpenseReportService.

  16. Set the Name property of the approveEvent object to the value "approveEvent".

  17. Add a generic EventHandler of the ExternalDataEventArgs type named approveEvent_Invoked to the Invoked event that is raised by the approveEvent object.

    this.approveEvent.EventName = "ExpenseReportApproved";
    this.approveEvent.InterfaceType = typeof(IExpenseReportService);
    this.approveEvent.Name = "approveEvent";
    this.approveEvent.Invoked += new
        System.EventHandler<ExternalDataEventArgs>(this.approveEvent_Invoked);
    
  18. Set the EventName property for the rejectEvent object to the value "ExpenseReportRejected".

  19. Set the InterfaceType property of the rejectEvent object to the System.Type of the IExpenseReportService.

  20. Set the Name property of the rejectEvent object to the value "rejectEvent".

  21. Add a generic EventHandler of the ExternalDataEventArgs type named rejectEvent_Invoked to the Invoked event that is raised by the rejectEvent object.

    this.rejectEvent.EventName = "ExpenseReportRejected";
    this.rejectEvent.InterfaceType = typeof(IExpenseReportService);
    this.rejectEvent.Name = "rejectEvent";
    this.rejectEvent.Invoked += new
        System.EventHandler<ExternalDataEventArgs>(this.rejectEvent_Invoked);
    
  22. Add the listenApproveReject object to the Activities collection of the workflow.

    Make sure that you add this object after the line that adds the evaluateExpenseReportAmount object.

    this.Activities.Add(this.evaluateExpenseReportAmount);
    this.Activities.Add(this.listenApproveReject);
    this.Name = "ExpenseReportWorkflow";
    this.CanModifyActivities = false;
    

Raising the Event from the Host Application

To raise the event from the host application

  1. In the approveButton_Click method of the MainForm class, raise the ExpenseReportApproved event, passing null (Nothing in Visual Basic) and a new ExternalDataEventArgs object that is initialized with the workflowInstance InstanceId as parameters.

  2. Set the Height property of the form equal to the MinimumSize.Height property.

  3. Set the Enabled property of the submitButton Button control to true.

    private void approveButton_Click(object sender, EventArgs e)
    {
        // Raise the ExpenseReportApproved event back to the workflow
        reportApproved(null, new ExternalDataEventArgs
            (this.workflowInstance.InstanceId));
        this.Height = this.MinimumSize.Height;
        this.submitButton.Enabled = true;
    }
    
  4. In the rejectButton_Click method of the MainForm class, raise the ExpenseReportRejected event, passing null (Nothing in Visual Basic) and a new ExternalDataEventArgs object that is initialized with the workflowInstance InstanceId as parameters.

  5. Set the Height property of the form equal to the MinimumSize.Height property.

  6. Set the Enabled property of the submitButton Button control to true.

    private void rejectButton_Click(object sender, EventArgs e)
    {
        // Raise the ExpenseReportRejected event back to the workflow
        reportRejected(null, new ExternalDataEventArgs
            (this.workflowInstance.InstanceId));
        this.Height = this.MinimumSize.Height;
        this.submitButton.Enabled = true;
    }
    
  7. Build and run the application.

    When you submit an expense report amount, the form expands to show the Approve and Reject buttons and a message that is received from the workflow. Clicking one of the buttons does the following:

    1. Collapses the form.

    2. Raises an event back to the workflow.

    3. Retrieves the Results property from the workflow.

    4. Displays it on the form.

Output from Task 2

Compiling the Code

For information about compiling your code, see Compiling the Code.

For a finished version of the tutorial, see Completed Sequential Workflow Tutorial.

See Also

Reference

ListenActivity
EventDrivenActivity
IEventActivity
CallExternalMethodActivity
HandleExternalEventActivity
ExternalDataEventArgs

Copyright © 2007 by Microsoft Corporation. All rights reserved.
Last Published: 2010-03-04