演练:创建带 Visual Basic 界面的 SQL Server 工作流应用程序
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/modcore/html/dewlkWalkthroughCreatingWorkflowApplicationForSQLServerWithVisualBasicInterface.asp
引言
Microsoft® Office XP Developer 包含 SQL Server 工作流设计器,该设计器提供了一个稳固的核心服务集,使用这些服务可以创建功能强大的跟踪应用程序。工作流过程及其相关用户界面通常可称为 Web 应用程序,其中包含一组使用 Microsoft® Access 开发的数据访问页。但是,根据用户的要求以及应用程序中需要的功能,可用许多不同的开发工具开发到工作流过程的界面。
其中的一种开发工具就是 Microsoft® Visual Basic® 6.0,它是 Microsoft® Windows® 平台最流行的开发工具之一。此演练阐述了如何在 Visual Basic 中创建界面,以使用工作流设计器中的核心功能。此示例界面是比较基本的,所以您可以将这些概念应用到您的应用程序中。您可以复制本文中提供的代码片断并粘贴到您的应用程序中,而无需重新键入。
此示例使用作为模板随工作流设计器而提供的问题跟踪示例数据库。有关从模板安装数据库和工作流过程的详细信息,请参阅基于模板创建工作流应用程序。
先决条件
要按照本文中的过程操作并创建 Visual Basic 界面,您必须在服务器和客户机上安装以下软件和组件:
- 一台安装了 SQL Server 工作流服务的服务器。
- 服务器上的问题跟踪示例模板的一个实例。
- 在开发计算机上安装了 Visual Basic 6.0。
什么是工作流应用程序?
工作流应用程序使用工作流设计器提供的一个或多个功能,使业务处理系统化并在数据库上实施业务规则。使用工作流设计器创建的典型应用程序拥有一个 SQL Server 数据库以及使用数据访问页创建的用户界面。有了数据访问页,开发人员就可以使用 Microsoft® Office Developer 工作流工具栏控件(包含在工作流设计器中)提供 Web 页界面所需的大部分功能。
Visual Basic 界面
本文中创建的 Visual Basic 界面的结构与工作流设计器中作为模板提供的基于 Web 的问题跟踪示例应用程序很相似。此应用程序包含以下用户界面元素:网格窗体 (Form1) 和明细窗体 (Form2),前者显示问题的摘要,而后者则显示问题的详细资料。用户通过这两个窗体与数据库进行交互。
网格窗体 (Form1)
网格窗体使用 Hierarchical FlexGrid (ModHFGrid) 控件,在问题跟踪示例数据库中提供一个问题列表。在网格窗体上部有一组命令按钮,通过这些按钮可以访问为工作流过程定义的事件。这组按钮称为工作流工具栏。有关示例,请参阅下图。
网格窗体 (Form1)
虽然完整的网格窗体很简单,但您可以通过它了解如何在 Visual Basic 中使用工作流设计器的功能。
明细窗体 (Form2)
明细窗体是数据绑定的窗体,它用于查看和修改问题跟踪示例数据库中的各个行。通过选择网格窗体上工作流工具栏中列出的某个事件,就可显示明细窗体。因为几乎所有的工作流设计器功能都是在网格窗体中实现的,所以创建明细窗体时所花的时间非常少。有关示例,请参阅下图。
明细窗体 (Form2)
第 1 步:设计网格窗体
网格窗体用于提供问题跟踪示例数据库中存储的所有问题的列表或摘要。此窗体是一个带有 Hierarchical FlexGrid 控件的标准 Visual Basic 窗体。数据绑定是使用数据环境设计器完成的。
创建数据环境
数据环境设计器提供了一个设计时界面,用于指定运行时要访问的数据。设计器在运行时生成 Microsoft® ActiveX® 数据对象 (ADO) 连接、命令以及记录集,您可以使用编程方法操纵它们。
另外,Visual Basic 给开发人员提供了一种方法,将“数据环境”中定义的命令对象自动绑定到窗体上的数据识别控件。这样,无需编程就可在 Visual Basic 窗体上显示数据。
创建数据环境
- 启动 Visual Basic,并从“新建工程”对话框中选择“标准 EXE”。
- 从“工程”菜单中选择“添加 Data Environment”。
注意 如果此菜单项不可用,您必须使用“部件”对话框启用数据环境设计器。从“工程”菜单中选择“部件”,并在“设计器”选项卡中,选择 Data Environment。
新的数据环境总是使用名为 "Connection1" 的连接对象创建。连接对象定义了哪个 SQL Server 和数据库包含要使用的数据。
- 用鼠标右键单击 Connection1,然后选择“属性”。
- 从提供者的列表中选择 Microsoft OLE DB Provider for SQL Server,并单击“下一步”。
- 在“选择或输入服务器名称”对话框中,输入 SQL Server 的名称,然后选择“使用 Windows NT 集成安全设置”。
- 在“在服务器上选择数据库”对话框中,输入或选择要使用的数据库名称。
- 单击“确定”。
连接对象将定义要访问的数据库。必须定义一个指定要访问哪个表或视图的命令对象。例如,在问题跟踪数据库中,应该使用 IssuesBaseView 视图。此视图包含 Issues 表和所有查找表中的所有字段(如类别、优先级和状态)。
- 用鼠标右键单击 Connection1,然后选择“添加命令”。就会在 Connection1 下面列出一个新项,即 Command1。
- 用鼠标右键单击 Command1,然后选择“属性”。
- 在“命令名称”中输入 IssuesBaseView。
- 从“数据库对象”列表中,选择“视图”,并从“对象名称”列表中选择 dbo.IssuesBaseView。
- 单击“确定”。
数据环境窗口就会列出 IssuesBaseView 命令及其下面的视图中的所有字段。
现在,从 IssuesBaseView 返回的数据就在使用该 Data Environment 对象的应用程序中可用。
创建 Hierarchical FlexGrid 控件
Hierarchical FlexGrid ActiveX 控件提供了一种显示一个数据源中多行数据的简便方法,这是因为它支持直接绑定到 Data Environment 对象中定义的 ADO 对象。此控件还提供了内置属性页,可更方便地设置网格中要显示的字段的格式。
创建 Hierarchical FlexGrid 控件
- 排列窗口,使 Data Environment 窗口和 Form1 在屏幕上均可见。
- 在 Data Environment 窗口中,用鼠标右键单击 IssuesBaseView,然后将它拖到 Form1。
- 从快捷方式菜单中选择 Hierarchical Flex Grid。
就会在窗体上创建一个 Hierarchical FlexGrid 控件。另外,由于从 Data Environment 拖动 IssuesBaseView 节点就会创建该控件,所以网格自动绑定到该视图中的数据中。
- 调整网格的大小,使之涵盖大部分窗体。
使用 Hierarchical FlexGrid 控件属性页,可以修改网格的运行时显示方式和行为。
- 选择 Hierarchical FlexGrid 控件,打开“视图”菜单,然后单击“属性页”。
- 在“通用”选项卡中,将“焦点区域”属性指定为 None,而将“选择模式”属性指定为 1 – By Row,并单击“确定”。
设置这些属性可使用户每次只能在网格中选择一行,并确保整行突出显示。
另外,您可以更改网格,使之仅显示 IssuesBaseView 中的某些字段,并更改字段显示的顺序。
- 用鼠标右键单击 Hierarchical FlexGrid 控件,然后选择“检索结构”。
该控件绑定的 IssuesBaseView 中的字段就会在网格中显示。这是网格中字段的默认布局 。
- 选择 Hierarchical FlexGrid 控件,打开“视图”菜单,单击“属性页”,然后选择“带区”。
- 在该框中,清除那些不想显示的字段。在此示例中,只选定以下字段:ItemID、AssignedTo、Subject 和 Status。
- 选择 ItemID 字段,并按上箭头键,直到该字段成为列表中的第一个字段为止。
注意 这一步对于本演练的以后部分非常重要,这是因为如果 ItemID 字段不是网格中的第一个字段的话,此示例无法工作。
- 单击“确定”
网格中列出的字段更改为属性页中选定的字段。
运行网格窗体
网格窗体的基本设计现已完成。从“运行”菜单中选择“启动”来运行应用程序。
Form1 显示了数据库中问题的列表。如果未在数据库中输入任何问题,那么就不会列出任何问题。
注意 只显示那些选定的字段。
如果已列出数据库中的问题,则单击某一行就会突出显示整行。这是 FocusRect 和 SelectionMode 属性设置启用的行为。
第 2 步:创建工作流工具栏
既然基本网格窗体可以工作了,现在就可添加一些工作流设计器所特有的功能。有了工作流工具栏,用户就可以使用为工作流过程定义的事件。针对问题跟踪数据库定义的事件包括:Resolve、Close、Edit、Active 等等。
创建工作流工具栏需要以下两个主要步骤:第一步是对返回有关工作流过程的信息(如定义的事件)的数据库执行一组查询,第二步是使用返回的信息动态地创建工具栏。
使用数据环境读取工作流信息
正如数据环境设计器可用来定义数据以确定在 Hierarchical FlexGrid 控件中显示哪些数据一样,它还是读取工作流信息的重要途径。它提供了一种直观定义所需查询的方法,并且简化了读取信息所需的代码。
在此示例中,在添加其他命令对象时使用的 Data Environment 对象也用于检索 IssuesBaseView 数据。或者,如果您要将“用户数据”与“工作流信息”查询从逻辑上分开,则可以再创建一个 Data Environment 对象。
创建工作流查询对象
- 在“工程窗口”中双击 DataEnvironment1,显示 Data Environment 窗口。
- 用鼠标右键单击 Connection1,然后选择“添加命令”。
就会在 Connection1 下面列出一个新项,即 Command1。
- 用鼠标右键单击 Command1,然后选择“属性”。
- 输入 Actions 作为“命令名称”。
- 选择“SQL 语句”,并在编辑框中输入以下 SQL SELECT 语句:
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
- 单击“确定”。
命令对象 Actions 用于返回所有可用事件的列表,这些事件是为与 Issues 表关联的工作流过程定义的。
对于过程中定义的每个事件,IssuesWorkflowActions 表中均有一行与之对应,Caption 字段指定在用户界面中应该列出的文本。IssuesWorkflow 表包含工作流规则以及每个事件所需的其他信息,如为特定操作引发的工作流事件。因此,两个表的联接可用于合并表,这样一次查询就可以返回所需的全部信息。
- 重复以上步骤。在“命令名称”中输入 AvailableActions。在“SQL 语句”编辑框中输入以下语句:
SELECT IssuesWorkflowActions.Caption, IssuesWorkflowView.State, IssuesWorkflowView.Next_State FROM IssuesWorkflowView INNER JOIN IssuesWorkflowActions ON IssuesWorkflowView.Id = IssuesWorkflowActions.WorkflowId WHERE (State = ?)OR (State = -1)
命令对象 AvailableActions 用于动态读取特定状态下可用的事件。例如,在问题跟踪示例数据库中,如果某一行的状态为 Active (StatusID = 1),则可用事件包括 Resolve 和 Edit,但不包括 Close 或 Activate。
SQL SELECT 语句中包含的问号是查询参数,每次执行该命令时,可在运行时提供该参数动态修改 WHERE 子句。
- 重复以上步骤。在“命令名称”中输入 NextState。在“SQL 语句”编辑框中输入以下语句:
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)
当从一个状态转换到另一个状态时,命令对象 NextState 用于检索下一状态的值。例如,在问题跟踪示例数据库中,当用户执行 Resolve 事件时,这意味着行的 StatusID 字段就会从 1 变为 2。此查询用于确定 2 是下一个 StatusID 字段值。
注意 此 SQL SELECT 语句还使用参数在运行时动态地提供 WHERE 子句。
在完成这些步骤后,Data Environment 对象除包含原始的 IssuesBaseView 命令对象外,还包含三个新命令对象:Actions、AvailableActions 和 NextState。
创建工作流工具栏
现在,可以使用 Data Environment 对象中的命令对象获取工作流信息。下一步是使用返回的信息来创建一个列出所有可用事件的用户界面。
这里创建的用户界面包含由一系列 CommandButton 组成的控件数组 — 每个事件对应一个控件。这是一个很基本的示例,但它提供了创建更高级界面所需的概念。大多数工作是在运行时使用代码完成的,因为在设计时不知道哪些事件可用。
创建工作流工具栏
- 在“工程窗口”中双击 Form1
,
显示 Form1 窗口。 - 单击“工具箱”上的 CommandButton 对象,并在窗体的左上角绘制一个 CommandButton。
在设计时,只创建一个用作模板的按钮。对于每个可用事件,CommandButton 都被复制并被移到先前那个按钮旁,在窗体上部形成一系列按钮。
- 在“属性”窗口中,将 Command1 的 (name) 属性改为 cmdAction,并将 Index 属性改为 0。
将 Index 属性改为 0 将使 CommandButton 变成一个控件数组,该控件数组在运行时包含多个命令对象。
- 打开“视图”菜单,然后单击“代码”以打开“代码编辑器”。
- 添加以下例程:
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
此例程完成以下操作:
- 创建 Data Environment 对象的一个实例,该对象包含检索工作流信息的查询。
- 执行 Actions 命令。
- 处理查询返回的每一行。
- 将设计时绘制的按钮用于第一个事件。但是,对于此后的任何事件,必须在运行时动态创建 CommandButton。新按钮直接放在前一个 CommandButton 的右侧。
- 将 CommandButton 标题更改为工作流事件信息中定义的标题,并使用 Tag 属性存储事件名称。用户以后执行该事件时,就会使用该事件名称。
- 浏览到下一个事件。
- 在“代码编辑器”中,添加以下例程:
Private Sub Form_Load() BuildActions End Sub
这将导致在窗体初次加载时执行 BuildActions 例程。
运行网格窗体
通过运行网格窗体来测试工作流工具栏的创建。从“运行”菜单中选择“启动”来运行应用程序。
您应该在窗体上部看到一系列按钮,它将列出问题跟踪数据库工作流过程中的每个事件。
更新工作流工具栏
工作流工具栏中列出的事件是否可用取决于当前选定的问题。只有选定问题的有效事件才可用。例如,如果问题是 Active,则 Closed 不可用,因为此时它不是有效事件。启用或禁用工具栏上的 CommandButton 必须基于当前选定的问题。
更新工作流工具栏
- 将以下例程添加到 Form1 代码模块中:
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
此例程完成以下操作:
- 创建 Data Environment 对象的一个实例,该对象包含检索工作流信息的查询。
- 执行 AvailableActions 命令并传递状态值。它将状态值传递给该命令,并用状态值替换查询中的参数(问号)。
- 处理每个按钮并使其不可用。
- 处理查询返回的每一行。
- 浏览这些按钮,查找与当前行标题值匹配的按钮标题。每找到一个匹配标题,就启用该按钮一次,因为查询指示该事件对此状态有效。
- 移到查询的下一行。
- 将以下代码添加到 Form1 代码模块中:
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
此例程完成以下操作:
- 该例程是基于 Hierarchical FlexGrid 控件的 RowColChange 事件的。只要在网格中选定了其他行,就会引发该事件。
- 记录集的 MoveFirst 和 Find 方法用于确保记录集的当前行与 Hierarchical FlexGrid 控件上突出显示的行相同。这可以通过使用该网格的 TextMatrix 属性,从 Hierarchical FlexGrid 控件上突出显示的行检索 ItemID 字段值来实现。
- 在 Data Environment 记录集中找到突出显示的记录时,从记录集的 StatusID 字段中检索行的当前状态。
- 在“代码编辑器”中,找到 Form_Load 例程,然后添加
MSHFGrid1_RowColChange
行,因此它将包含:Private Sub Form_Load() BuildActions MSHFlexGrid1_RowColChange End Sub
这可确保既可在用户更改选定行时又可在窗体初次加载时更新工具栏。
确保将 RowColChange 命令排在 BuildActions 之后执行。否则,所有按钮将不可用。
现在,您可以对它进行测试了。从“运行”菜单上选择“启动”。您会看到工作流工具栏。在该工具栏上,相应的事件可用,而其他事件不可用。选择一个处于不同状态的问题,工作流工具栏就会自动更新。
这将完成网格窗体主要功能的创建。下一步是创建明细窗体,使得在工作流工具栏上选定事件时通过显示明细窗体可以执行这些事件。
第 3 步:设计明细窗体
明细窗体用于一次查看和修改一个问题。明细窗体与网格窗体类似,它与数据环境中的 IssuesBaseView 命令对象绑定在一起。但是,这些字段不与网格绑定在一起,而是绑定到各个文本框控件。
启用 IssuesBaseView 更新
默认情况下,在“数据环境”中创建的命令对象是只读的。要使命令对象可以更新,还需要其他设置和一行代码。
启用 IssuesBaseView 命令更新
- 在“工程窗口”中双击 DataEnvironment1,显示 Data Environment 窗口。
- 用鼠标右键单击 IssuesBaseView,然后选择“属性”。
- 在“高级”选项卡上,从“锁定类型”列表中选择“3 – 开放式”。
- 单击“确定”。
除了设置“锁定类型”属性外,还必须更改另一个属性值。
工作流设计器的功能之一就是允许用户设置行级权限。此功能是通过视图实施的,视图只根据行级权限返回用户可访问的行。
为防止用户不使用行级权限和查看他们无权访问的行,不向任何用户授予基表的读或写权限。
对于问题跟踪示例应用程序来说,Issues 基表是不可访问的,但是 IssuesView 和 IssuesBaseView 视图是可访问的。要更新 Issues 表视图 (IssuesBaseView),必须通知命令对象只使用基表的主键来更新。为此,将属性设置更改为 Update Criteria 属性。
只要打开了命令对象,就必须设置该属性。这可通过将代码添加到 Data Environment 后面模块中的 Initialize 事件来完成。
设置 Update Criteria 属性实施行级权限
- 选择 DataEnvironment1,打开“视图”菜单然后单击“代码”。
- 在“代码编辑器”中,添加以下例程:
Private Sub DataEnvironment_Initialize() DataEnvironment1.rsIssuesBaseView.Properties("Update Criteria") = 0 End Sub
创建明细窗体
可以与创建网格窗体相同的方法来创建明细窗体 — 将 Data Environment 拖放到窗体上。
创建明细窗体
- 从“工程”菜单中选择“添加窗体”。
- 在“添加窗体”对话框中,选择“窗体”,然后单击“打开”。
- 排列这些窗口,使 Data Environment 窗口和 Form2 均在屏幕上可见。
- 将 Data Environment 中 IssuesBaseView 下面列出的 AssignedTo 字段拖到 Form2 上。
这样就在窗体上创建一个标题为 "AssignedTo" 的“文本框”控件。将该控件设置为自动绑定到 AssignedTo 字段。
- 重复以上步骤,分别为以下每个字段创建一个“文本框”控件。
字段 AssignedTo Subject Description ResolutionDescription ResolutionID 明细窗体是从网格窗体访问的。用户必须能够将所做的更改保存到行中,然后关闭明细窗体。
- 单击“工具箱”上的 CommandButton 对象,并在窗体下部绘制两个 CommandButton 控件。
- 选择 Command1。
- 在“属性”窗口中,将 (name) 属性改为 cmdOK,将 Caption 改为 OK,将 Default 改为 True。
- 选择 Command2。
- 在“属性”窗口中,将 (name) 属性改为 cmdCancel,将 Cancel 改为 True,将 Caption 改为 Cancel。
- 选择 cmdOK,打开“视图”菜单然后单击“代码”。
- 在“代码编辑器”中,添加以下例程:
Private Sub cmdCancel_Click() DataEnvironment1.rsIssuesBaseView.Cancel Unload Form2 End Sub Private Sub cmdOK_Click() DataEnvironment1.rsIssuesBaseView.Update Unload Form2 End Sub
cmdCancel 例程完成以下操作:
- 执行 Cancel 方法,取消对窗体所做的任何更改。
- 关闭明细窗体。
cmdOK 例程完成以下操作:
- 执行 Update 方法,提交对该窗体所做的任何更改。
- 关闭明细窗体。
通过执行工具栏上的事件显示明细窗体
对于工作流工具栏上定义的每个用户操作,都有一个定义所执行功能的关联事件。用户控制的事件和典型功能如下所示:
- OnCreate 在数据库中插入一个新行。
- OnChange 为更改为其他状态的某一行修改工作流状态,并为某个状态中的转换修改工作流字段以外的一个字段。
- OnDelete 从数据库中删除一行。
对于其中的每个事件(OnDelete 除外),用户应该可以查看和修改 Issues 表中的所有字段。另外,对于 OnChange 事件,必须根据该行的当前状态确定下一状态,并且使用新的状态来更新工作流字段。
通过单击工作流栏上的按钮来执行这些事件,该工作流栏是通过 cmdAction 控件数组创建的。因此,必须将代码添加到 cmdAction_Click 事件上,该事件识别单击的按钮并执行基于与该按钮事件相关联的事件的功能。切记当工作流工具栏生成时,会将该控件数组的 Tag 属性设置为与用户操作关联的事件。代码必须检索该值,并根据该值执行相应的功能。
要使窗体执行事件
- 选择 Form1,打开“视图”菜单然后单击“代码”。添加以下代码以处理 OnCreate 事件。对于 OnCreate 来说,该代码必须显示明细窗体并创建一个新行。
Private Sub cmdAction_Click(Index As Integer) Select Case cmdAction(Index).Tag Case "OnCreate" Load Form2 DataEnvironment1.rsIssuesBaseView.AddNew Form2.Show vbModal, Me
此部分例程完成以下操作:
- 开始将 Select Case 与 Tag 属性进行比较,后者包含单击 CommandButton 的事件名称。
- 如果事件是 OnCreate 但仍不可见,则将明细窗体 (Form2) 装入内存中。
- 通过加载明细窗体,创建与 IssueBaseView 命令对象关联的记录集。执行记录集的 AddNew 方法,以创建一个新行。
- 模式显示明细窗体,并将网格窗体作为它的父窗口。
- 将以下代码直接放在前面处理 OnUpdate 事件的代码后面。对于 OnUpdate,用户必须查看明细窗体以编辑当前选定的行。
Case "OnUpdate" Form2.Show
继续执行此例程可完成以下操作:
- 如果事件是 OnUpdate,可直接显示明细窗体 (Form2)。因为此窗体所绑定的记录集与 Hierarchical FlexGrid 相同,并且该窗体已将记录集定位到同一突出显示的行,所以只有该窗体才必须显示。
- 将以下代码直接加到前面提供 OnDelete 事件功能的代码后面。对于 OnDelete,甚至不必显示明细窗体。用户只需验证应该删除的当前行。
Case "OnDelete" If MsgBox("Are you sure?", vbYesNo, "Delete Issue") = _ vbYes Then DataEnvironment1.rsIssuesBaseView.Delete End If
此代码执行以下操作:
- 如果事件是 OnDelete,则显示一个消息框,确认用户是否要删除当前行。
- 如果用户选择“是”,通过执行 Delete 方法选定该行。
- 将以下代码直接加到前面提供 OnChange 事件功能的代码后面,它是实现工作流功能的关键。对行所设置的状态取决于用户的操作。
添加以下代码:
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
此代码完成以下操作:
- 如果事件是 OnChange,检索当前行的状态以及用户所单击按钮的标题。
- 将此信息作为参数传递以执行在“数据环境”中创建的 NextState 命令对象。执行完它以后,返回的行将包含该行应当被设置成的下一个 StatusID。
- 检索该值,并将当前行的 StatusID 列设为该值。
- 显示明细窗体,这样用户就可以修改任何其他字段。
- 添加此代码的其余部分完成该例程。添加此代码以更新 Hierarchical FlexGrid 控件,这样它就包含用户使用明细窗体所做的可能修改:
DataEnvironment1.rsIssuesBaseView.Requery Set MSHFlexGrid1.DataSource = DataEnvironment1 MSHFlexGrid1.DataMember = "IssuesBaseView" MSHFlexGrid1_RowColChange End Sub
此代码完成以下操作:
- 要求命令对象绑定到 Hierarchical FlexGrid 控件,以便返回任何所做的更改。
- 重新将 Hierarchical FlexGrid 控件绑定到 Data Environment,使所有更新均在网格上体现出来。
- 当状态已更改时,就调用 RowColChange 事件更新工作流工具栏。
第 4 步:测试工作流功能
以上步骤完成了应用程序的所有工作流功能。请按照以下步骤测试工作流的功能。
测试工作流功能
- 从“运行”菜单中,选择“启动”。就会显示 Form1 以及可用的正确事件。
- 在工作流工具栏上,单击“新建”。明细窗体 (Form2) 就会出现,并带有一个新行。
- 在 AssignedTo、Subject 和 Description 字段中输入信息。因为这是一个新问题,所以您不需要在 ResolutionDescription 或 ResolutionType 字段中添加任何内容。
- 单击“确定”。
注意 问题跟踪示例数据库包含工作流脚本,这些脚本要求 AssignedTo 字段值与用户目录中的某个用户关联。如果您在 AssignedTo 字段中输入的用户不在用户目录中,就会收到一条错误信息。
注意 因为此代码并不对它进行任何错误检查,所以必须单击“结束”终止应用程序,然后重新启动。要完成应用程序,必须添加错误检查例程来相应地处理此类错误。
在将问题成功添加到数据库中后,在网格窗体中就会有一个状态为 Active 的新行,该状态为新行的默认设置。
- 选择新添加的问题,在工作流工具栏上单击 Resolve。
明细窗体就会出现,并带有添加的新行。虽然看起来只是在编辑行,实际上代码已通过将 StatusID 字段从 0 (Active) 改为 1 (Resolved) 而自动执行了工作流转换。在单击“确定”之后,才会提交此更改。
- 为 ResolutionDescription 和 ResolutionID 输入一个值(如 1)。
您必须为这些字段输入一个值,因为问题跟踪示例应用程序包含的工作流脚本就会在从 Active 转换为 Resolved 时验证这些字段。
- 单击“确定”。
就会更新网格窗体,并且会发现输入的问题状态由 Active 变成 Resolved。另外,工作流工具栏已自动更新,以便体现这种更改。
通过选择问题并工作流工具栏上的事件,来测试其余事件。
结论
虽然通常使用基于 Web 的用户界面设计工作流应用程序,但是也可使用能访问 SQL Server 数据的任何开发工具来开发界面。在本演练中,您创建的是利用工作流设计器中的一组核心服务的 Visual Basic 界面。
通过读取工作流信息,界面可以动态地生成一个工作流工具栏,引导用户完成数据库中定义的工作流过程。此功能和一组数据绑定的 Visual Basic 窗体关联,以提供一个完整的应用程序。
利用该应用程序中说明的基本概念,并在 Visual Basic 或其他任何可访问 SQL Server 数据的开发工具中创建您自己的应用程序。
请参阅
演练:用 SQL Server 工作流设计器开发工作流应用程序 | 演练:规划一个销售管理 SQL Server 工作流应用程序 | 开发 SQL Server 工作流应用程序 | ModHFGrid 控件