Walkthrough: Creating a Workflow Application for SQL Server with a Visual Basic Interface
This content is no longer actively maintained. It is provided as is, for anyone who may still be using these technologies, with no warranties or claims of accuracy with regard to the most recent product version or service release.
Introduction
Microsoft® Office XP Developer contains the Workflow Designer for SQL Server, which provides a robust core set of services that can be used to build powerful tracking applications. The workflow process and its associated user interface typically are described as a Web application that contains a set of data access pages developed using Microsoft® Access. However, an interface to the workflow process can be developed using a number of different development tools, depending on the requirements of the users and the features desired in the application.
One such development tool is Microsoft® Visual Basic® 6.0, which is one of the most popular development tools for the Microsoft® Windows® platform. This walkthrough explains how to build an interface in Visual Basic that takes advantage of the core features available in the Workflow Designer. This sample interface has been kept basic, so you can apply these concepts to your own applications. The code snippets throughout the article are provided for you to copy and paste into your application without having to retype them.
This example uses the Issue Tracking sample database that is provided as a template with the Workflow Designer. For more information about installing the database and workflow process from the template, see Creating Workflow Applications Based on Templates.
Prerequisites
To follow the procedures in this article and create the Visual Basic interface, you must have the following software and components installed on the server and client:
- A server set up with the Workflow Services for SQL Server.
- An instance of the Issue Tracking sample template on the server.
- Visual Basic 6.0 installed on the development computer.
What Is a Workflow Application?
A workflow application systemizes a business process and enforces business rules on a database by using one or more of the features provided by the Workflow Designer. A typical application created using the Workflow Designer has a SQL Server database and a user interface created using data access pages. Data access pages make it possible for the developer to use the Microsoft® Office Developer Workflow Toolbar control, which is included with the Workflow Designer, to provide most of the functionality required of the Web page interface.
The Visual Basic Interface
The Visual Basic interface created in this article is structured in a similar manner to the Web-based Issue Tracking sample application provided as a template in the Workflow Designer. The application contains the following user interface elements: a Grid form (Form1) that shows a summary of issues and a Detail form (Form2) that shows details about a specific issue. The user interacts with the database through these two forms.
Grid Form (Form1)
The Grid form uses the Hierarchical FlexGrid (ModHFGrid) control to provide a list of the Issues in the Issue Tracking sample database. Along the upper portion of the Grid form, a series of command buttons provides access to events defined for the workflow process. This series of buttons is referred to as the workflow toolbar. See the following illustration for an example.
Grid form (Form1)
Although the completed Grid form is simple, it does provide you with an understanding of how to use the features of the Workflow Designer in Visual Basic.
Detail Form (Form2)
The Detail form is a data-bound form that is used to view and modify individual rows in the Issue Tracking sample database. It is displayed by selecting one of the events listed on the workflow toolbar on the Grid form. Because nearly all of the Workflow Designer functionality is implemented in the Grid form, only minimal time is spent on creating this form. See the following illustration for an example.
Detail form (Form2)
Step 1: Design the Grid Form
The Grid form is used to provide a list or summary of all issues stored in the Issue Tracking sample database. The form is a standard Visual Basic form with a Hierarchical FlexGrid control. The data binding is done using the Data Environment designer.
Creating the Data Environment
The Data Environment designer provides a design-time interface for specifying the data you want to access at run time. The designer generates Microsoft® ActiveX® Data Objects (ADO) Connections, Commands, and recordsets at run time that you can manipulate programmatically.
In addition, Visual Basic provides a way for developers to automatically bind Command objects defined in the Data Environment to data-aware controls on a form. This makes it possible to display data on a Visual Basic form without any programming.
To create the Data Environment
Start Visual Basic, and select Standard EXE from the New Project dialog box.
From the Project menu, select Add Data Environment.
**Note **If this menu item is not available, you must make the Data Environment designer available from the Components dialog box. Select Components from the Project menu, and in the Designers tab, select Data Environment.
A new Data Environment always is created with one Connection object named "Connection1." The Connection object defines which SQL Server and database contains the data to use.
Right-click Connection1, and select Properties.
Select Microsoft OLE DB Provider for SQL Server from the list of providers, and click Next.
Enter the name of your SQL Server in the Select or enter a server name dialog box, and select Use Windows NT integrated security.
Enter or select the name of the database to use in the Select the database on the server dialog box.
Click OK.
The Connection object defines the database to access. A Command object must be defined that specifies which table or view to access. For example, in the Issue Tracking database, the IssuesBaseView view should be used. This view contains all fields in the Issues table and all the lookup tables (such as Category, Priority, and Status).
Right-click Connection1, and select Add Command. A new item, Command1, is listed under Connection1.
Right-click Command1, and select Properties.
Enter IssuesBaseView for the Command Name.
Select View from the Database Object list, and select dbo.IssuesBaseView from the Object Name list.
Click OK.
The Data Environment window lists the IssuesBaseView Command and all fields within the view under it.
The data returned from the IssuesBaseView is now available in the application using this Data Environment object.
Creating the Hierarchical FlexGrid Control
The Hierarchical FlexGrid ActiveX control provides an easy way to display multiple rows of data from a data source, because it supports direct binding to an ADO object defined in a Data Environment object. The control also provides built-in property pages that make it easier to format the fields you want displayed within the grid.
To create the Hierarchical FlexGrid control
Arrange the windows, so both the Data Environment window and Form1 are visible on the screen.
Right-click IssuesBaseView in the Data Environment window, and drag it to Form1.
Select Hierarchical Flex Grid from the shortcut menu.
A Hierarchical FlexGrid control is created on the form. In addition, because dragging the IssuesBaseView node from the Data Environment created it, the grid automatically binds to the data from that view.
Resize the grid, so it covers most of the form.
Using the Hierarchical FlexGrid control property pages, the run-time display and the behavior of the grid can be modified.
Select the Hierarchical FlexGrid control, open the View menu and click Property Pages.
On the General tab, specify None for the FocusRect property and 1 – By Row for the SelectionMode property, and click OK.
Setting these properties makes it possible for the user to select only one row at a time in the grid and ensures the entire row is highlighted.
In addition, you can change the grid to show only certain fields from the IssuesBaseView and change the order of the fields displayed.
Right-click the Hierarchical FlexGrid control, and select Retrieve Structure.
The fields available in the IssuesBaseView to which the control is bound are displayed in the grid. This is the default layout of the fields in the grid.
Select the Hierarchical FlexGrid control, open the View menu and click Property Pages, and then select the Bands tab.
In the box, clear those fields you do not want displayed. In this example, only the following fields are selected: ItemID, AssignedTo, Subject, and Status.
Select the ItemID field, and press the UP ARROW key until this field is the first field in the list.
**Note **This step is important for later in the walkthrough, because this example will not work if the ItemID field is not the first field in the grid.
Click OK
The fields listed in the grid change to those you selected in the property page.
Running the Grid Form
The basic design of the Grid form is now complete. Select Start from the Run menu to run the application.
Form1 displays a list of the issues in your database. If you have not entered any issues in the database, then none are listed.
**Note **Only those fields selected are displayed.
If you have issues in the database and you click a row, the entire row is highlighted. This is the behavior enabled by the FocusRect and SelectionMode property settings.
Step 2: Build the Workflow Toolbar
Now that the basic Grid form is working, it is time to add some Workflow Designer-specific functionality. The workflow toolbar makes the events that have been defined for the workflow process available to the user. In the case of the Issue Tracking database, the events defined include Resolve, Close, Edit, Active, and so on.
Two main steps are required to build the workflow toolbar. The first step is to execute a set of queries against the database that returns information about the workflow process (such as the events defined), and the second step is to use the information returned to build the toolbar dynamically.
Using the Data Environment to Read Workflow Information
Just as the Data Environment designer was used to define the data to specify what data to display in the Hierarchical FlexGrid control, the Data Environment is also a great way to read the workflow information. It provides a way to define visually the queries required, and it simplifies the code required to read the information.
In this example, the same Data Environment object is used to retrieve the IssuesBaseView data as is used when adding an additional Command object to it. Alternatively, you could create an additional Data Environment object if you want to keep a logical separation between "user data" and "workflow information" queries.
To create the workflow queries objects
Double-click DataEnvironment1 in the Project Window to display the Data Environment window.
Right click Connection1, and select Add Command.
A new item, Command1, is listed under Connection1.
Right-click Command1, and then select Properties.
Enter Actions for the Command Name.
Select SQL Statement, and enter the following SQL SELECT statement in the edit box:
SELECT IssuesWorkflowActions.Caption, Min(Event) As Event, Min(Position) As Position FROM IssuesWorkflowActions INNER JOIN IssuesWorkflowView ON IssuesWorkflowActions.WorkflowId = IssuesWorkflowView.Id GROUP BY IssuesWorkflowActions.Caption ORDER BY 3
Click OK.
This Command object, Actions, is used to return a list of all of the available events defined for the workflow process associated with the Issues table.
The IssuesWorkflowActions table contains a row for each event defined in the process, and the Caption field specifies the text that should be listed in the user interface. The IssuesWorkflow table contains the workflow rules along with other information required for each event, such as the workflow event fired for a particular action. Therefore, a two-table join is used to combine the tables, so all the information required is returned in one query.
Repeat the earlier steps. Enter AvailableActions for the Command Name. Enter the following in the SQL Statement edit box:
SELECT IssuesWorkflowActions.Caption, IssuesWorkflowView.State, IssuesWorkflowView.Next_State FROM IssuesWorkflowView INNER JOIN IssuesWorkflowActions ON IssuesWorkflowView.Id = IssuesWorkflowActions.WorkflowId WHERE (State = ?) OR (State = -1)
This Command object, AvailableActions, is used to read the events dynamically that are available based on a specific state. For example, in the Issue Tracking sample database, if a row has a state of Active (StatusID = 1), the available events include Resolve and Edit but not Close or Activate.
The question mark included in the SQL SELECT statement is a query parameter, which can be provided at run time to alter dynamically the WHERE clause each time the Command is executed.
Repeat the earlier steps. Enter NextState for the Command Name. Enter the following in the SQL Statement edit box:
SELECT IssuesWorkflowView.Id, Status.Status, IssuesWorkflowView.State, IssuesWorkflowActions.Caption, IssuesWorkflowView.Next_State, IssuesWorkflowView.Event FROM IssuesWorkflowView LEFT OUTER JOIN Status ON IssuesWorkflowView.Next_State = Status.StatusID INNER JOIN IssuesWorkflowActions ON IssuesWorkflowView.Id = IssuesWorkflowActions.WorkflowId WHERE (IssuesWorkflowActions.Caption = ?) AND (IssuesWorkflowView.State = ? OR IssuesWorkflowView.State = - 1)
This Command object, NextState, is used to retrieve the next state value when transitioning from one state to another. For example, in the Issue Tracking sample database, when the user executes the Resolve event, it means the StatusID field of the row is changing from 1 to 2. This query is used to identify that 2 is the next value for the StatusID field.
**Note **This SQL SELECT statement also uses parameters to dynamically supply the WHERE clause at run time.
When you have completed these steps, the Data Environment object contains the original IssuesBaseView Command object along with the three new Command objects: Actions, AvailableActions, and NextState.
Creating the Workflow Toolbar
The workflow information is now available using the Command objects in the Data Environment object. The next step is to use the information returned to build a user interface that lists the available events.
The user interface created here contains a control array of a series of CommandButtons — one for each event. This is a very basic example, but it provides the concepts required to create more elaborate interfaces. Most of the work is done using code at run time, because at design time, it is unknown what events are available.
To create the workflow toolbar
Double-click Form1 in the Project Window to display the Form1 window.
Click the CommandButton object on the Toolbox, and draw a CommandButton at the upper left of the form.
At design time, only one button is created, which is used as a template. For each event available, the CommandButton is copied and moved next to the previous one to form a series of buttons across the upper portion of the form.
In the Properties window, change the (name) property of Command1 to cmdAction and the Index property to 0.
Changing the Index property to 0 causes the CommandButton to become a control array that can contain multiple Command objects at run time.
Open the View menu and click Code to open the Code Editor.
Add the following routine:
Public Function BuildActions() As Variant Dim DataEnvironment1 As New DataEnvironment1, intControl As Integer DataEnvironment1.Actions intControl = 0 While Not DataEnvironment1.rsActions.EOF If intControl <> 0 Then Load cmdAction(intControl) cmdAction(intControl).Top = cmdAction(intControl - 1).Top cmdAction(intControl).Left = _ cmdAction(intControl - 1).Width + cmdAction(intControl _ - 1).Left End If With cmdAction(intControl) .Visible = True .Enabled = True .Caption = _ DataEnvironment1.rsActions.Fields("Caption").Value .Tag = DataEnvironment1.rsActions.Fields("Event").Value End With intControl = intControl + 1 DataEnvironment1.rsActions.MoveNext Wend End Function
This routine accomplishes the following:
- Creates an instance of the Data Environment object that contains the queries to retrieve the workflow information.
- Executes the Actions command.
- Walks through each row returned from the query.
- Uses the button drawn at design time for the first event. However, for any event after that, a CommandButton must be created dynamically at run time. The new button is positioned immediately to the right of the previous CommandButton.
- Changes the caption of the CommandButton to the caption defined in the workflow event information and uses the Tag property to store the event name. The event name is used later when the user executes the event.
- Navigates to the next event.
In the Code Editor, add the following routine:
Private Sub Form_Load() BuildActions End Sub
This causes the BuildActions routine to be executed when the form is first loaded.
Running the Grid Form
Test the building of the workflow toolbar by running the Grid form. Select Start from the Run menu to run the application.
You should see a series of buttons along the upper portion of the form that lists each of the events available in the workflow process of the Issue Tracking database.
Updating the Workflow Toolbar
Whether an event listed on the workflow toolbar is available depends on the currently selected issue. Only valid events for the selected issue should be available. For example, if an issue is Active, then Closed is not available, because it is not a valid event during the Active state. The CommandButtons on the toolbar must be made available and unavailable based on the currently selected issue.
To update the workflow toolbar
Add the following routine to the Form1 code module:
Private Sub UpdateActions(intState As Integer) Dim DataEnvironment1 As New DataEnvironment1, intControl As Integer DataEnvironment1.AvailableActions intState For intControl = 0 To cmdAction.UBound cmdAction(intControl).Enabled = False Next While Not DataEnvironment1.rsAvailableActions.EOF For intControl = 0 To cmdAction.UBound If cmdAction(intControl).Caption = _ DataEnvironment1.rsAvailableActions.Fields("Caption"). _ Value Then cmdAction(intControl).Enabled = True End If Next DataEnvironment1.rsAvailableActions.MoveNext Wend End Sub
This routine accomplishes the following:
- Creates an instance of the Data Environment object that contains the queries to retrieve the workflow information.
- Executes the AvailableActions command and passes in the state value. This passes the state value to the command, replacing the parameter (question mark) in the query with the state value.
- Walks through each button and makes it unavailable.
- Walks through each row returned from the query.
- Walks through the buttons to find a button caption that matches the current row's caption value. Each time it finds a match, the button is made available, because the query indicates that the event is valid for this state.
- Moves to the next row in the query.
Add the following code to the Form1 code module:
Private Sub MSHFlexGrid1_RowColChange() DataEnvironment1.rsIssuesBaseView.MoveFirst DataEnvironment1.rsIssuesBaseView.Find "ItemID = " + _ CStr(MSHFlexGrid1.TextMatrix(MSHFlexGrid1.Row, 0)) UpdateActions _ DataEnvironment1.rsIssuesBaseView.Fields("StatusID").Value End Sub
This routine accomplishes the following:
- The routine is based on the RowColChange event of the Hierarchical FlexGrid control. Whenever a different row is selected in the grid, this event is fired.
- The MoveFirst and Find methods of the recordset are used to make sure the current row of the recordset is the same row that is highlighted on the Hierarchical FlexGrid control. This is done by retrieving the ItemID field value from the highlighted row in the Hierarchical FlexGrid control using the TextMatrix property of the grid.
- Retrieves the current state of the row from the StatusID field from the recordset when the highlighted record is found in the Data Environment recordset.
In the Code Editor, find the Form_Load routine, and add the line
MSHFGrid1_RowColChange
so it contains:Private Sub Form_Load() BuildActions MSHFlexGrid1_RowColChange End Sub
This makes sure the toolbar is updated not only when the user changes the selected row but also when the form is first loaded.
Make sure to place the RowColChange command after the execution of BuildActions. Otherwise, no buttons will be available.
Now you are ready to test it out. Select Start from the Run**menu. You will see the workflow toolbar with the appropriate events available and the others unavailable. Select an issue that has a different status, and the workflow toolbar automatically updates.
This completes the building of the primary functionality of the Grid form. The next step is to create the Detail form and make possible the execution of the events by displaying the Detail form when an event is selected on the workflow toolbar.
Step 3: Design the Detail Form
The Detail form is used to view and modify one issue at a time. Similar to the Grid form, the Detail form is bound to the IssuesBaseView Command object in the Data Environment. However, instead of being bound to a grid, the fields are bound to individual TextBox controls.
Enabling Updates on IssuesBaseView
By default, Command objects created in the Data Environment are read-only. An additional setting and a line of code are required to make the Command object updateable.
To enable updates on IssuesBaseView command
- Double-click DataEnvironment1 in the Project Window to display the Data Environment window.
- Right-click IssuesBaseView, and select Properties.
- On the Advanced tab, select 3 – Optimistic from the Lock Type list.
- Click OK.
In addition to setting the Lock Type property, another property value must be changed.
One of the features of the Workflow Designer is that it makes it possible for users to set row-level permissions. This functionality is enforced through a view that only returns the rows to which the user has access, based on the row-level permissions.
To prevent users from bypassing the row-level permissions and viewing rows to which they do not have access, the base table does not make read or write permissions possible to any users.
In the case of the Issue Tracking sample application, the base table Issues is not accessible, but the views IssuesView and IssuesBaseView are accessible. To make updates to the Issues table view, IssuesBaseView, the Command object must be told to make updates only using the primary key of the base table. To do this, change the property setting to the Update Criteria property.
This property must be set whenever the Command object is opened. This can be done by adding code to the Initialize event in the module behind the Data Environment.
To set the Update Criteria property to enforce row-level permissions
Select DataEnvironment1, open the View menu and click Code.
In the Code Editor, add the following routine:
Private Sub DataEnvironment_Initialize() DataEnvironment1.rsIssuesBaseView.Properties("Update Criteria") = 0 End Sub
Creating the Detail Form
The Detail form can be created in the same manner as the Grid form — by dragging the Data Environment onto a form.
To create the Detail form
From the Project menu, select Add Form.
In the Add Form dialog box, select Form, and then click Open.
Arrange the windows, so both the Data Environment window and Form2 are visible on the screen.
Drag the AssignedTo field listed under IssuesBaseView in the Data Environment to Form2.
A TextBox control is created on the form with a caption of "AssignedTo." The TextBox is set up to bind to the AssignedTo field automatically.
Repeat the steps to create a Textbox control for each of the following fields:
Field AssignedTo Subject Description ResolutionDescription ResolutionID The Detail form will be accessed from the Grid form. The user must have a way to save changes made to the row and then close the Detail form.
Click the CommandButton object on the Toolbox, and draw two CommandButtons controls on the lower portion of the form.
Select Command1.
In the Properties window, change the (name) property to cmdOK, the Caption to OK, and Default to True.
Select Command2.
In the Properties window, change the (name) property to cmdCancel, Cancel to True, and Caption to Cancel.
Select cmdOK, open the View menu and click Code.
In the Code Editor, add the following routines:
Private Sub cmdCancel_Click() DataEnvironment1.rsIssuesBaseView.Cancel Unload Form2 End Sub Private Sub cmdOK_Click() DataEnvironment1.rsIssuesBaseView.Update Unload Form2 End Sub
The cmdCancel routine accomplishes the following:
- Executes the Cancel method to undo any changes made on the form.
- Closes the Detail form.
The cmdOK routine accomplishes the following:
- Executes the Update method to commit any changes made on the form.
- Closes the Detail form.
Displaying the Detail Form by Executing an Event on the Toolbar
For each user action defined on the workflow toolbar, there is an associated event that defines the functionality that is executed. The user-controlled events and typical functionality are as follows:
- **OnCreate **Inserts a new row into the database.
- **OnChange **Modifies the workflow state for a row that is changed to a different state, and modifies a field other than the workflow field for a transition within a state.
- **OnDelete **Deletes a row from the database.
For each of these events, except OnDelete, the user should have the opportunity to view and modify all fields from the Issues table. In addition, for the OnChange event, the next state based on the current state of the row must be identified, and the workflow field must be updated with this new state.
The events are executed by clicking a button on the workflow bar, which is built using the cmdAction control array. Therefore, code must be added on the cmdAction_Click event that identifies the button clicked and executes functionality based on the event associated with the button event. Remember that when the workflow toolbar is generated, the Tag property of the control array is set to the event associated with the user action. Code must retrieve this value and, based on the value, execute the appropriate functionality.
To make it possible for the form to execute events
Select Form1, open the View menu and click Code. Add the following code to handle the OnCreate event. For OnCreate, the code must display the Detail form and create a new row.
Private Sub cmdAction_Click(Index As Integer) Select Case cmdAction(Index).Tag Case "OnCreate" Load Form2 DataEnvironment1.rsIssuesBaseView.AddNew Form2.Show vbModal, Me
This section of the routine accomplishes the following:
- Begins a Select Case comparison against the Tag property, which contains the event name of the CommandButton clicked.
- Loads the Detail form (Form2) into memory if the event is OnCreate but is not visible yet.
- Creates the recordset associated with the IssueBaseView Command object by loading the Detail form. The AddNew method of the recordset is executed, so a new row is created.
- Makes the Detail form visible in a modal state, with the Grid form as its parent window.
Add the following code immediately after the earlier code to handle the OnUpdate event. For OnUpdate, the user must see the Detail form to edit the currently selected row.
Case "OnUpdate" Form2.Show
Continuing this routine accomplishes the following:
- Immediately shows the Detail form (Form2) if the event is OnUpdate. Because the form is bound to the same recordset as the Hierarchical FlexGrid, the form already navigated the recordset to the same row that is highlighted, so the form only must be displayed.
Add the following code immediately after the earlier code to provide functionality for the OnDelete event. For OnDelete, the Detail form does not even have to be displayed. The user only must verify that the current row should be deleted.
Case "OnDelete" If MsgBox("Are you sure?", vbYesNo, "Delete Issue") = _ vbYes Then DataEnvironment1.rsIssuesBaseView.Delete End If
This code does the following:
- Displays a message box to confirm the user wants to delete the current row if the event is OnDelete.
- Selects the row by executing the Delete method if the user selects Yes.
Add the following code immediately after the earlier code to provide functionality for the OnChange event, which is central to the workflow functionality. The status to which the row is set depends on the action the user is taking.
Add the following code:
Case "OnTransition" intState = _ DataEnvironment1.rsIssuesBaseView.Fields("StatusID").Value strCaption = cmdAction(Index).Caption DataEnvironment1.NextState strCaption, intState intNextState = _ DataEnvironment1.rsNextState.Fields("Next_State").Value DataEnvironment1.rsIssuesBaseView.Fields("StatusID").Value _ = intNextState Form2.Show vbModal, Me End Select
This code accomplishes the following:
- Retrieves the status of the current row and the caption of the button that the user clicked if the event is OnChange.
- Passes this information as parameters to execute the NextState Command object that was created in the Data Environment. After it is executed, the row returned will contain the next StatusID to which that row should be set.
- Retrieves this value and sets the StatusID column of the current row to it.
- Shows the Detail form, so the user can modify any of the other fields.
Add the rest of this code to complete the routine. Add this code to update the Hierarchical FlexGrid control, so it contains any modifications that the user might have made using the Detail form:
DataEnvironment1.rsIssuesBaseView.Requery Set MSHFlexGrid1.DataSource = DataEnvironment1 MSHFlexGrid1.DataMember = "IssuesBaseView" MSHFlexGrid1_RowColChange End Sub
This code accomplishes the following:
- Requires the Command object bound to the Hierarchical FlexGrid control, so any changes made are returned.
- Rebinds the Hierarchical FlexGrid control to the Data Environment, so the updates are reflected in the grid.
- Calls the RowColChange event to update the workflow toolbar in case the state has changed.
Step 4: Test Workflow Functionality
The previous steps complete all workflow functionality for the application. Follow the next steps to test the functionality.
To test the workflow functionality
From the Run menu, select Start. Form1 is displayed with the proper events available.
Click New on the workflow toolbar. The Detail form (Form2) appears with a new row.
Enter information in the AssignedTo, Subject, and Description fields. Because this is a new issue, you are not required to add anything to the ResolutionDescription or ResolutionType fields.
Click OK.
**Note **The Issue Tracking sample database contains workflow scripts that require the value of the AssignedTo field to be associated with a user in the user directory. If you enter a user in the AssignedTo field who is not in the user directory, you will receive an error message.
**Note **Because this code does not have any error-checking for this, you must click End to stop the application, and then restart it. To complete your application, you must add error-checking routines to handle such errors appropriately.
After you successfully add the issue to the database, you will have a new row in the Grid form with a status of Active, the default for new rows.
Select the newly added issue, and click Resolve on the workflow toolbar.
The Detail form appears with the new row you added. Although it looks as if the row is being edited only, the code has executed a workflow transition automatically by changing the StatusID field from 1 (Active) to 2 (Resolved). This change is not committed until you click OK.
Enter a value for ResolutionDescription and ResolutionID (such as 1).
You must enter a value for these fields, because the Issue Tracking sample application contains workflow scripts that validate these fields on a transition from Active to Resolved.
Click OK.
The Grid form is updated, and you will see the status of the issue you entered has changed from Active to Resolved. In addition, the workflow toolbar has been updated automatically to reflect the change.
Test the rest of the events available by selecting issues and clicking events on the workflow toolbar.
Conclusion
Although a workflow application is typically designed with a Web-based user interface, the interface can be developed using any development tool that can access SQL Server data. In this walkthrough, you created a Visual Basic interface that takes advantage of the core set of services available in the Workflow Designer.
By reading workflow information, the interface is able to generate dynamically a workflow toolbar that guides the user in following the workflow process defined in the database. This functionality is tied around a set of data-bound Visual Basic forms to provide a complete application.
Take the basic concepts illustrated in this application, and create your own applications in Visual Basic or any other development tool that can access SQL Server data.
See Also
Walkthrough: Developing a Workflow Application Using Workflow Designer for SQL Server | Walkthrough: Planning a Sales Management Workflow Application for SQL Server | Developing Workflow Applications for SQL Server | ModHFGrid Control