sharepoint工作流开发(VS2008)

更新时间:2024-04-12 13:49:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

7.4 采用Visual Studio 2008 开发工作流模板

本节讲述采用Visual Studio 2008开发SharePoint工作流模板的一般步骤和方法。为了使读者更好地理解本节的内容,本节在讲述基本原理和操作的同时会附带讲解一个实例工作流的开发,这个工作流是一个文档审批工作流:提交者上传文档,然后启动工作流,最后提交给审批人审批。

7.4.1 创建工作流项目

Step1 新建项目。打开Visual Studio 2008新建项目,选择“Workflow”中的“SharePoint 2007 Sequential Workflow”项目模板,如图7-40所示。

图7-40 新建项目

Step2 指定调试工作流所用的站点路径,如图7-41所示。

图7-41 指定调试工作流所用的站点路径

Step3 指定工作流用来调试时附加到的列表。若列表不存在,则先到站点中创建,如图7-42所示。

图7-42 制定工作流用来调试时附加到的列表

Step4 指定工作流调试时的启动方式为手工启动,如图7-43所示。

图7-43 指定工作流调试时的启动方式

以上操作完成之后,可以看到VS 2008中如图7-44所示的布局。该图中左边工具栏上是系统提供的所有活动组件,中间是工作流设计器界面,右边是项目文件。

图7-44 操作完后的布局 SharePoint 2007 Sequential Workflow项目模板会自动添加一个OnWorkflowActivated活动,这个活动在工作流启动的时候执行,它的WorkflowProperties属性绑定到工作流的workflowProperties字段,workflowProperties的类型是SPWorkflowActivationProperties,存放了跟工作流相关的数据,如表7-1所示。 表7-1 SPWorkflowActivationProperties属性说明 属 性 AssociationData HistoryList HistoryListId InitiationData Item List Originator OriginatorUser Site Web TaskList 类 型 String SPList Guid String SPListItem SPList String SPUser SPSite SPWeb SPList 说 明 工作流关联数据,通过关联表单提供 存放工作流历史记录的列表 存放工作流历史记录的列表ID 工作流初始化数据,通过初始化表单提供 工作流附加到的列表项对象 工作流附加到的列表 启动工作流的用户账号 启动工作流的用户对象 工作流运行的站点集 工作流运行的网站 存储工作流任务的列表 7.4.2 任务的分配 SharePoint工作流是任务驱动的工作流,工作流按照各种逻辑分配任务给用户,用户通过完成任务跟工作流进行交互,驱动流程前进。任务分配跟以下几个活动有关。 l createTask:通过createTask活动创建任务,工作流代码必须处理createTask活动的MethodInvoking事件,创建任务ID,指定任务操作用户。 l onTaskChanged:通过onTaskChanged活动,等待用户完成任务,并可以处理Invoked方法,按照用户的输入进行逻辑处理。

l completeTask:通过completeTask活动,完成用户的任务。

一个任务的分配过程,都是需要以上3个活动进行配合的。下面是具体分配任务的操作过程。

Step1 从工具栏中拖曳createTask到设计器中,如图7-45所示。

Step2 指定createTask活动的CorrelationToken属性为“task1Token”,OwnerActivityName为“Workflow1”,如图7-46所示。

图7-45 从工具栏中拖曳CreateTask到设计器 图7-46 指定CreateTask活动的属性

Step3 绑定createTask活动的TaskId属性到工作里的字段。单击“TaskId”属性的设置按钮,在弹出的属性绑定窗口选择绑定到新成员标签,输入名称为“task1Id”,选择创建字段,如图7-47所示。

图7-47 绑定CreateTask活动的TaskId属性到工作里的字段

Step4 绑定createTask活动的TaskProperties属性到工作流的字段task1Properties。

Step5 处理createTask的MethodInvoking事件。双击createTask,在自动生成的MethodInvoking事件处理函数中写入如下代码。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); //生成任务ID this.task1Properties.Title = \文档审批\

this.task1Properties.AssignedTo = \设置任务操作人 }

Step6 拖曳onTaskChanged到工作流设计器中,如图7-48所示。

图7-48 拖曳onTaskChanged到工作流设计器

Step7 设置onTaskChanged活动的CorrelationToken属性为“task1Token”,如图7-49所示。 Step8 将onTaskChanged活动的TaskId属性绑定到已有的task1Id字段,如图7-50所示。

图7-49 CorrelationToken属性为“createTask1”

图7-50 TaskId属性绑定到已有的task1Id字段

Step9 将onTaskChanged活动的BeforeProperties和AfterProperties属性均绑定到已有task1Properties字段。

Step10 拖曳completeTask活动到工作流设计器中,如图7-51所示。

图7-51 拖曳CompleteTask活动到工作流设计器

Step11 设置completeTask活动的CorrelationToken属性为“task1Token”。 Step12 将completeTask活动的TaskId属性绑定到已有的task1Id字段。 Step13 设置completeTask活动的TaskOutcome属性为“完成”,如图7-52所示。

图7-52 设置TaskOutcome属性

以上是创建一个任务的基本过程。在实际过程中,任务操作人的获取可能有多种情形,比如从站点的某个组内获取用户,从第三方的角色管理系统中获取用户等。假设任务要分配给站点的部门经理组中的用户,则createTask活动的MethodInvoking事件可以如下。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); this.task1Properties.Title = \文档审批\ //获取到部门经理网站组

SPGroup group1 = this.workflowProperties.Web.SiteGroups[\部门经理\ SPUser user1 = group1.Users[0]; //获取部门经理网站组中的第一个用户 this.task1Properties.AssignedTo = user1.LoginName; //分配任务 }

createTask活动会在工作流对应的任务列表中创建一个任务列表项。在默认情况下,对任务列表具有操作权限的用户都可以操作这个任务列表项,但通常情况下,希望只有特殊的用户才可以进行操作,这就要用到createTask活动的SpecialPermissions属性。SpecialPermissions是一个集合类型,可以将有权限的用户加到它里面,实现对任务列表项的特殊权限控制。下面是具体的操作步骤。

Step1 选中createTask活动,单击SpecialPermissions属性的“绑定”图标,绑定属性到specialPermissions1字段中,如图7-53和图7-54所示。

图7-53 SpecialPermissions属性的绑定图标

图7-54 绑定属性到specialPermissions1字段

Step2 修改createTask的MethodInvoking事件处理方法,设置specialPermissions1集合,代码如下所示。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); this.task1Properties.Title = \任务标题\

this.task1Properties.AssignedTo = \ //设置任务权限

this.specialPermissions1.Add(this.task1Properties.AssignedTo,

SPRoleType.Contributor);

}

以上讲述的是单个任务的创建过程,重复这个过程,可以创建出多步的顺序审批流程。

7.4.3 工作流的测试和调试

上一节已经完成了任务分配的基本编码,直接按“F5”键即可部署和调试。如果只是单纯的部署,可以通过项目右键菜单的“Deploy”菜单项进行,如图7-55所示。

图7-55 右键菜单的“Deploy”菜单项

部署完成后,访问MOSS站点测试工作流关联的文档库(本节示例为名称为文档审批的文档库),新建或上传一个文档,然后选择名称栏右键菜单的“工作流”选项,选择要测试的工作流,如图7-56和图7-57所示。

图7-56 新建一个文档

图7-57 工作流选择

启动工作流后,返回文档库,会发现文档库上多出来一栏,以工作流的名称命名,可以称这一栏为工作流状态栏,如图7-58所示。

图7-58 工作流状态栏

单击工作流状态栏链接,可以转到工作流状态页面。在此页面,可以查看到工作流分配的所有任务情况,如图7-59所示。

图7-59 工作流状态页面

用具有编辑任务权限的用户登录站点,访问到工作流状态页面,通过任务标题栏的“编辑项目”菜单可以转到任务编辑页面,如图7-60所示。

图7-60 任务编辑页面

由于尚未定义任务操作页面,所以会看到如图7-61所示的默认任务编辑页面,单击“确定”按钮即可完成审批任务。

图7-61 默认任务编辑页面

完成任务之后,转回任务状态页面,可以看到任务的状态已经变成“已完成”,如图7-62所示。

图7-62 任务状态页面

以上是在测试时可进行的快捷操作。工作流实际运行时,不可能要求用户采用这样的操作方式,一般采用用户任务Web部件,让用户直接在站点首页集中处理工作流任务。

在站点首页进入编辑模式,选择添加Web部件,选中添加用户任务Web部件即可,如图7-63所示。

图7-63 选择用户任务Web部件

7.4.4 设计工作流模板的任务表单

上一节已经看到了默认的任务编辑页面,这显然是不符合实际要求,普通的审批页面一般具有一个意见框、一个批准和拒绝的选项。本节讲述如何采用InfoPath来开发自定义的任务操作界面。

1.设计表单

Step1 新建表单。打开InfoPath,选择“表单模板”单选按钮,确认选中“仅启动浏览器兼容性功能”复选框,如图7-64所示。

图7-64 新建表单

Step2 添加数据源域。在数据源中添加两个字段域,一个名称为“comments”,数据类型为“文本”;另一个名称为“approval”,数据类型为“boolean”,如图7-65和图7-66所示。

图7-65 添加数据源域

图7-66 添加数据源域

Step3 插入布局表格。选择“插入”菜单中的“版式表格”选项,插入一个3行1列的布局表格,如图7-67和图7-68所示。

图7-67 插入布局表格

图7-68 插入布局表格

Step4 设计表单字段。将审批意见域拖曳到布局表格上,并调整高度。将审批结果域拖曳到布局表格上,并且更改为选项按钮,分别在两个单项框后面添加批准和拒绝文字,如图7-69所示。

图7-69 设计表单字段

Step5 添加“提交”按钮。通过设计任务转到插入控件面板,拖曳一个按钮控件到布局表格中,双击按钮,在属性窗口中将按钮标签改为“提交”,如图7-70所示。

图7-70 添加提交按钮

Step6 添加按钮规则。单击“规则”按钮,在规则编辑窗口中单击“添加”按钮,如图7-71所示。在添加规则窗口单击“添加操作”按钮,如图7-72所示。

图7-71 添加按钮规则 图7-72 “添加操作”按钮

选择使用数据连结进行提交操作,单击“添加”按钮,如图7-73所示。在“数据连接向导”窗口中,选择“新建连接”和“仅提交数据”单选按钮,如图7-74所示。

图7-73 使用数据连接进行提交操作 图7-74 选择“新建连接”和“仅提交数据”

单击“下一步”按钮,选择“提交到宿主环境”单选按钮,如图7-75所示,再单击“下一步”按钮,在弹出的窗口中单击“完成”按钮,然后依次单击“确定”按钮,返回规则编辑窗口。在规则编辑窗口中添加关闭表单操作,如图7-76所示,最终设计好的表单如图7-77所示。

图7-75 选择提交到宿主环境 图7-76 添加关闭表单操作

图7-77 设计好的表单

2.发布表单

Step1 确认表单的安全级别为“完全信任”。通过“工具”菜单调出“表单选项”窗口,在“安全和信任”类别中选中表单的安全级别为“完全信任”,如图7-78和图7-79所示。

图7-78 调出“表单选项”窗口 图7-79 确认表单的安全级别为“完全信任”

Step2 单击设计任务面板中的“发布表单模板”链接,如图7-80所示。在“发布向导”窗口中选择“网络位置”单选按钮,单击“下一步”按钮,如图7-81所示。

图7-80 任务面板 图7-81 “发布向导”窗口

Step3 指定表单模板的发布位置为项目所在的目录,指定文件名为

“ApprovalForm.xsn”,单击“下一步”按钮,如图7-82所示。确保如图7-83所示的路径输入框为空,单击“下一步”按钮完成表单发布。

图7-82 指定表单模板的发布位置 图7-83 路径输入框

3.修改工作流的配置文件和代码

Step1 确保表单正确发布到项目目录中,如图7-84所示。

图7-84 确保表单正确发布到项目目录

Step2 修改feature.xml文件。在feature.xml文件的ElementManifests节点下添加如下代码,确保infopath表单能被Visual Studio自动发布。

最终的feature.xml文件如下所示。

ReceiverAssembly=\

Culture=neutral, PublicKeyToken=71e9bce111e9429c\

ReceiverClass=\ xmlns=\

Step3 修改workflow.xml文件。在workflow.xml文件的Workflow节点下添加如下属性,确保工作流创建的任务采用infopath表单内容类型。

TaskListContentTypeId=\

在MetaData节点下添加任务的FormURN注册,代码如下所示。

urn:schemas-microsoft-com:office:infopath:Task0:-myXSD-2008-10-02T19-07-06

FormURN的实际值可以通过infopath表单的“文件”→“属性”命令获得,如图7-85所示的ID域即是表单的FormURL。

图7-85 表单模板属性

Step4 修改greateTask的MethodInvoking事件处理方法,指定TaskType为0,代码如下。 private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); //生产任务ID this.task1Properties.Title = \文档审批\

this.task1Properties.AssignedTo = \指定任务操作人 this.task1Properties.TaskType = 0; //设置任务采用第一个任务表单 //将任务编辑权限分配给任务操作人

this.specialPermissions1.Add(this.task1Properties.AssignedTo,

SPRoleType.Contributor);

}

以上操作完成后可以再次部署工作流,启动流程后可以看到如图7-86所示的任务编辑页面。

图7-86 任务编辑页面

4.表单的校验步骤 InfoPath表单发布后,访问任务页面的时候可能会出现表单加载错误,这个现象大多数情形下是由表单本身引起的,可以先通过SharePoint管理中心的管理表单模板模块进行校验,确保表单校验成功。表单校验步骤如下。 Step1 访问应用程序管理中的管理表单模板模块,如图7-87所示。

图7-87 管理表单模板模块

Step2 单击“上载表单模板”链接,如图7-88所示。

图7-88 “上载表单模板”链接

Step3 单击“浏览”按钮找到项目目录中发布后的模板,再单击“校验”按钮,确定表单验证状态为“成功”,如图7-89和图7-90所示。若表单校验不成功,则按照提示信息操作。

图7-89 验证表单模板

图7-90 表单验证成功 不要单击“上载”按钮,工作流任务表单模板和工作流定义的Feature关联,安装Feature

之后表单模板会自动安装。

7.4.5 工作流代码给任务表单域赋值

上一节讲述了如何设计工作流的任务表单,以及如何让任务表单跟工作流的

任务关联起来。在很多情况下,工作流代码需要访问任务表单中的域,给某个域赋值或者获取某个域的值。

工作流代码不能直接给表单域赋值,给表单域赋值必须借助于辅助数据源来进行。以下是添加辅助数据源的步骤。

Step1 新建ItemMetadata.xml文件。新建一个文本文件,改名为ItemMetadata.xml,添加以下内容。

以ows开头的属性是辅助数据源中的字段,工作流代码可以控制这些字段的值,按照需要可以添加多个字段,但是要注意字段命名的格式以ows_开头。 Step2 添加数据连接。选择“工具”菜单中的“数据连接”命令,如图7-91所示。

图7-91 选择“数据连接”命令

Step3 在弹出的“数据连接”窗口中单击“添加”按钮,再在弹出的对话框中选择“新建连接”和“仅接收数据”单选按钮,如图7-92所示,单击“下一步”按钮。

图7-92 添加数据连接

Step4 选择“XML文档”单选按钮,如图7-93所示,单击“下一步”按钮。选择Step1中新建的“ItemMetadata.xml”文件作为数据文件,如图7-94所示。

图7-93 选择“XML文档”接收数据 图7-94 选择“ItemMetadata.xml”文件

Step5 确认选中如图7-95所示的单选按钮。输入数据连接名称为“ItemMetadata”,单击“完成”按钮,如图7-96所示。

图7-95 数据连结向导 图7-96 输入数据连接的名称

添加好辅助数据源后,需要将辅助数据源中的属性和表单域默认值关联起来。工作流代码可以控制辅助数据源中字段的值,但在默认情况下,辅助数据源是不会显示到表单上的,一般设置表单域的默认值为辅助数据源中字段的值,这样表单加载的时候即可显示辅助数据源中的字段数据。假设要在任务表单显示的时候,审批意见框默认显示辅助数据源中ows_comments字段的值,操作步骤如下。 Step1 选择主数据源中的“comments”域,弹出如图7-97所示的属性编辑窗口。 Step2 单击默认值区域中的编辑按钮,在“插入公式”窗口中单击“插入域或组”按钮,如图7-98所示。

图7-97 属性编辑窗口 按钮,如图7-99所示。

图7-98 单击“插入域或组”按钮

Step3 在“选择域或组”窗口中,切换到ItemMetadata辅助数据源,选择“ows_comments”域,单击“确定”

Step4 依次单击“确定”按钮,返回域或组属性编辑窗口,如图7-100所示,单击“确定”按钮。

图7-99 选择域 图7-100 设置初始值

Step5 表单修改好后,需要重新发布表单到工作流项目所在的目录。最后修改工作流代码,来给辅助数据源中的ows_comments域赋值。修改createTask的MethodInvoking事件处理方法如下。 private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); this.task1Properties.Title = \文档审批\

this.task1Properties.AssignedTo = \

this.task1Properties.TaskType = 0; //设置任务使用第一个任务表单 //设置infopath表单中的comments字段值

this.task1Properties.ExtendedProperties[\请在此输入您的审批意见\ //分配任务编辑权限

this.specialPermissions1.Add(this.task1Properties.AssignedTo,

SPRoleType.Contributor);

}

通过SPWorkflowTaskProperties类的ExtendedProperties属性可控制辅助数据源的值。

尽管辅助数据源中的域全部是以ows_开头,但是代码访问时不需要带ows_。

7.4.6 工作流代码获取任务表单域的值

在以上几节的示例中,任务提交完成后工作流代码并没有处理,在本章的文档审批示例流程中,审批人批准之后,文档才应该正式发布,若没有批准则不能发布。

SharePoint文档库本身支持内容审批功能,启用内容审批功能后,文档新建或上传后处于草稿状态,只有当有权限的用户审批之后,文档才能被普通用户浏览。

通过文档库设置中的版本控制设置可以启动内容审批功能,如图7-101所示。在“提交的项目是否需要内容审批”选项中选择“是”单选按钮,在“哪些用户可查看此文档库中的草稿项目”选项中选择“仅限可批准项目的用户(以及该项目的作者)”单选按钮可以查看草稿项目。

图7-101 启用内容审批

下面修改工作流代码,实现当用户操作任务表单时,选择“批准”则将文档的审批状态改为“已批准”,选择“拒绝”则将文档的状态改为“已拒绝”。 双击工作流设计器上的“onTaskChange”活动,在自动生成的Invoked事件处理函数中添加如下代码。

private void onTaskChanged1_Invoked(object sender, ExternalDataEventArgs e) {

//获取到任务表单中的approval字段

bool approval = Convert.ToBoolean(this.task1Properties.

ExtendedProperties[\

//获取到任务表单中的comments字段

string comments = \ SPModerationStatusType approvalState = approval ? SPModerationStatusType.

Approved : SPModerationStatusType.Denied;

SPListItem item = this.workflowProperties.Item;

item[\设置内容审批状态 item[\//设置内容审批批注 item.Update(); }

可以通过SPWorkflowTaskProperties类的ExtendedProperties属性获取表单域的数据。以上代码按照approval域的值设置列表项的_ModerationStatus字段为相应值,并把comments表单域的值赋给列表项的_ModerationComments字段。

7.4.7 工作流模板的关联表单

工作流模板的关联表单是当把一个工作流模板和某个列表(或文档库)关联起来时调用的表单,一般用来实现一些流程相关的配置。

在流程代码中,可以通过workflowProperties字段的AssociationData属性获取到关联表单的数据。AssociationData放置的是关联表单的XML格式的数据。

下面给文档审批流程示例添加一个功能为管理员将文档审批工作流模板附加到某个文档库时可以指定审批人,并且可以指定一些人员,发送提醒邮件。

1.设计表单模板

Step1 新建表单模板,保存为“AssociationForm.xsn”。

Step2 通过属性菜单,把数据源根节点的名称由“myFields”修改为“ConfigurationData”。

Step3 添加人员选择控件。在“设计任务”的“插入控件”面板单击“添加或删除自定义控件”链接,如图7-102所示。

图7-102 “插入控件”面板

在“添加或删除自定义控件”窗口中单击“添加”按钮,在弹出的窗口中选择“ActiveX控件”单选按钮,如图7-103所示。选择“Contact Selector”控件,如图7-104所示。

图7-103 选择控件类型 图7-104 选择控件

选择“不包括.cab文件”单选按钮,如图7-105所示。指定绑定属性为

“Value”,如图7-106所示。指定数据类型为“域或组”,如图7-107所示。

图7-105 指定安装选项 图7-106 指定绑定类型

图7-107 指定控件数据类型

Step4 配置人员选择控件的数据源。人员选择控件必须绑定到格式固定的组,首先添加一个名为“ApprovalUser”的组,然后在ApprovalUser组下添加一个名为“Person”的可重复组,如图7-108所示。在Person组下分别添加“DisplayName”、“AccountId”和“AccountType”3个文本域,最终数据源结构如图7-109所示。

图7-108 添加Person组

图7-109 数据源结构

Step5 将Contract Selector拖放到表单上,利用右键菜单的“更改绑定”命令绑定到ApprovalUser组,如图7-110所示。

图7-110 更改绑定

Step6 按照Step4、Step5的操作,添加一个“MailTo”组,并添加“MailSubject”和“MailBody”两个文本字段,如图7-111所示。

图7-111 数据源

Step7 按照如图7-81所示的向导完成表单设计(参考7.4.4节的添加“提交”按钮操作),完成后的效果如图7-112所示。

图7-112 表单效果

Step8 发布表单。确认表单的安全级别为“完全信息”,将表单发布到项目所在目录,发布文件名为“AssociationForm.xsn”。

2.修改配置文件

接下来需要修改配置文件,将AssociationForm.xsn跟工作流模板进行关联。

Step1 修改feature.xml。在ElementManifests节点下添加如下代码。

Step2 修改workflow.xml文件。在Workflow节点下添加如下属性。 AssociationUrl=\

在MetaData节点下添加如下属性。

urn:schemas-microsoft-com:office:infopath:AssociationForm: -myXSD-2008-10-04T07-45-17

FormURN可以通过infopath属性窗口获得。

3.修改工作流代码

下面修改工作流代码,在创建任务的时候从关联表单数据中获取审批用户,并给相应的用户发送邮件。关联表单数据的访问有两种方法。

(1)直接通过XML对象模型访问,示例代码如下。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); this.task1Properties.Title = \文档审批\ XmlDocument doc = new XmlDocument(); //加载关联表单的XML数据

doc.LoadXml(workflowProperties. AssociationData); //设置名称空间

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable); nsmgr.AddNamespace(\ //查询审批人账号

string aprovalUserAccount =

doc.DocumentElement.SelectSingleNode(\ AccountId\

//将任务分配给审批人

this.task1Properties.AssignedTo = aprovalUserAccount; this.task1Properties.TaskType = 0;

this.task1Properties.ExtendedProperties[\请在此输入您的审批意见\ this.specialPermissions1.Add(this.task1Properties.AssignedTo,

SPRoleType.Contributor);

}

以上代码采用XmlDocument从关联表单数据中获取到审批人账号,然后分配审批任务。

(2)由表单的schema生成对应的类,直接将关联表单数据反序列化为这个类,通过这个类来访问。

Step1 通过InfoPath的文件菜单,将表单另存为源文件,如图7-113所示。

图7-113 另存为源文件

Step2 打开Visual Studio 2008命令提示。

(选择“开始”菜单中的“Microsoft Visual Studio 2008”→“Visual Studio Tools”→“Visual Studio 2008 Command Prompt”) Step3 在命令行窗体中使用cd命令转向Step1中保存的源文件路径。 Step4 输入“xsd myschema.xsd/c”命令,并到源文件路径找到生成的myschema.cs文件,改名为“ConfigurationData.cs”,将

ConfigurationData.cs复制到工作流项目中。为了方便关联表单数据的访问,在工作流中声明以下属性。

private ConfigurationData _ConfigurationData; ///

///配置数据 ///

public ConfigurationData ConfigurationData { get {

if (_ConfigurationData == null)

{ //将关联表单数据反序列化为相应的对象

XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData)); XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(

this.workflowProperties.AssociationData));

_ConfigurationData = (ConfigurationData)serializer.Deserialize(

reader);

}

return _ConfigurationData; } }

相应的createTask1_MethodInvoking方法可以修改如下。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.task1Id = Guid.NewGuid(); this.task1Properties.Title = \文档审批\ //通过反序列化后的类获取审批人账号

this.task1Properties.AssignedTo = this.ConfigurationData.ApprovalUser[0].

AccountId;

this.task1Properties.TaskType = 0;

this.task1Properties.ExtendedProperties[\请在此输入您的审批意见\ this.specialPermissions1.Add(this.task1Properties.AssignedTo,

SPRoleType.Contributor);

}

邮件发送逻辑的实现需要采用sendEmail活动实现,并且收件人是非必填字段,需要采用IfElse活动来判断是否需要执行sendEmail活动。

Step1 拖曳IfElse活动到工作流设计器中,如图7-114所示。

图7-114 添加IfElse活动

Step2 指定ifElseBranchActivity1的条件类型为“Code Condition”,条件函数为“NeedSendMail”,双击“Condition”输入框,如图7-115所示。

图7-115 指定Condition

Step3 在自动生成的Condition方法中添加如下代码。

///

///判断是否需要发送邮件 ///

///

private void NeedSendMail(object sender, ConditionalEventArgs e) { //如果配置了邮件地址则需要发送邮件

e.Result = this.ConfigurationData.MailTo != null && this.ConfigurationData.MailTo.Length > 0 ; }

Step4 拖曳sendEmail活动到ifElseBranchActivity1,并设置其CorrelationToken为task1Token,如图7-116所示。

图7-116 添加sendEmail活动

Step5 处理sendEmail活动的MethodInvoking方法,代码如下。

private void sendEmail1_MethodInvoking(object sender, EventArgs e) {

string to = \

foreach (Person p in this.ConfigurationData.MailTo) {

Contact contact = Contact.FromName(p.AccountId,

this.workflowProperties.Web);

if (to != \ to += contact.EmailAddress; }

this.sendEmail1.To = to;

this.sendEmail1.Subject = this.ConfigurationData.MailSubject; this.sendEmail1.Body = this.ConfigurationData.MailBody; }

以上代码遍历配置类中的账号,采用Contact.FromName方法转换成Contact对象,通过Contact对象的EmailAddress取到用户的邮件。

4.测试关联表单

采用Visual Studio 2008部署工作流时,关联表单不会出现,要测试关联表单,必须手工将工作流模板关联到文档库或列表。部署工作流后,采用以下步骤测试关联表单。

Step1 进入工作流设置页面,单击“添加工作流”链接,如图7-117所示。

图7-117 工作流设置

Step2 在添加或更改工作流页面,选择要附加的工作流

(CodeArt.WorkflowDemo1),输入工作流名称,如图7-118所示,单击“下一步”按钮。

图7-118 添加工作流

Step3 配置关联表单。在关联表单设置页面(如图7-119所示),输入相关信息,单击“提交”按钮完成工作流关联操作。

图7-119 关联表单

7.4.8 工作流模板的初始化表单

初始化表单是启动流程时调用的表单,供启动流程的用户填写一些数据。在流程代码中,可以通过workflowProperties字段的InitiationData属性获取到初始化表单的数据。InitiationData放置的是初始化的xml格式的数据。 若存在关联表单,初始化表单的数据源架构必须跟关联表单一致,关联表单的数据将作为初始化表单的默认值。为了保持架构一致,初始化表单可以直接将关联表单另存为一份副本进行修改。

下面给文档审批流程示例添加一个功能:当启动文档审批流程时,用户可以重新指定审批人,重新指定接受提醒邮件的人员。

1.设计表单模板

Step1 将AssociationForm.xsn另存为InitiationForm.xsn。 Step2 修改表单,如图7-120所示。

图7-120 InitiationForm表单样式

Step3 发布表单。确认表单的安全级别为“完全信息”,将表单发布到项目所在目录,发布文件名为“InitiationForm.xsn”。

2.修改配置文件

接下来需要修改配置文件,将InitiationForm.xsn跟工作流模板进行关联。 Step1 修改feature.xml。在ElementManifests节点下添加如下代码。

Step2 修改workflow.xml文件。在Workflow节点下添加如下属性。 InstantiationUrl=\

在MetaData节点下添加如下属性。

urn:schemas-microsoft-com:office:infopath:InitiationForm: -myXSD-2008-10-04T07-45-17

FormURN可以通过infopath属性窗口获得。

3.修改工作流代码

修改工作流代码,从初始化表单数据中获取数据,进行分配任务和发送邮件操作。只需要将ConfigurationData属性的获取逻辑修改如下。

private ConfigurationData _ConfigurationData; ///

///配置数据 ///

public ConfigurationData ConfigurationData { get

{

if (_ConfigurationData == null)

{ //将初始表单数据反序列化为相应的对象

XmlSerializer serializer = new XmlSerializer(typeof(

ConfigurationData));

XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(

this.workflowProperties.InitiationData));

_ConfigurationData = (ConfigurationData)serializer.Deserialize(

reader);

}

return _ConfigurationData; } }

因为初始化表单和关联表单的数据源架构一致,所以仍然可以直接把初始化表单数据直接反序列化为ConfigurationData类型。

7.4.9 复合任务活动和多步审批流程

读者如果按照7.4.2节的描述来实现多步的审批流程时会发现,每次创建任务都需要createTask、onTaskChanged和completeTask 3个活动配合来完成,这是一个很烦琐的过程,并且流程图的可视化效果也变差了。WF工作流框架中的活动支持复合,即多个单一的活动可以组合成一个活动,本节实现这样一个任务复合活动并用它来实现多步的文档审批流程。创建任务复合活动步骤如下。

Step1 新建一个活动,名称为“TaskActivity”。

Step2 拖曳createTask、onTaskChanged和completeTask 3个活动到设计器中。 Step3 拖曳一个code活动到设计器中,如图7-121所示。

图7-121 TaskActivity

Step4 设置createTask、onTaskChanged和completeTask的correlationToken属性为“taskToken”。 Step5 将createTask、onTaskChanged和CompleteTask的TaskId绑定到活动类的taskId字段,将createTask的SpecialPermission属性绑定到活动类的specialPermission字段。

Step6 将createTask的TaskProperties属性绑定到活动类的TaskProperties属性。TaskActivity的任务数据应该公开供外部调用,所以将TaskProperties声明为属性,而不是字段,如图7-122所示。

图7-122 绑定到活动类的TaskProperties属性

Step7 将onTaskChanged的BeforeProperties和AfterProperties属性均绑定到活动类的TaskProperties属性。

Step8 任务的操作人需要由外部代码来指定,TaskActivity需要提供一个事件,供外部代码处理,以便指定任务操作人。首先定义一个事件参数类。 ///

///任务事件参数 ///

public class TaskEventArgs : EventArgs {

///

///任务属性 ///

public readonly SPWorkflowTaskProperties TaskProperties; public TaskEventArgs(SPWorkflowTaskProperties taskProperties) {

TaskProperties = taskProperties; } }

在TaskActivity类中添加事件声明代码。 //任务创建前触发的事件

[DesignerSerializationVisibilityAttribute( DesignerSerializationVisibility.Visible)]

[BrowsableAttribute(true)] [CategoryAttribute(\杂项\

public event EventHandler TaskCreating; Step9 处理createTask的MethodInvoking事件,代码如下。

private void createTask1_MethodInvoking(object sender, EventArgs e) {

this.taskId = Guid.NewGuid();

if(this.TaskProperties == null ) //实例化TaskProperties

this.TaskProperties = new SPWorkflowTaskProperties (); if (TaskCreating != null) //触发事件

TaskCreating(this, new TaskEventArgs(this.TaskProperties)); //设置任务编辑权限

if (!String.IsNullOrEmpty(this.TaskProperties.AssignedTo)) this.specialPermissions.Add(this.TaskProperties.AssignedTo,

SPRoleType.Contributor);

}

以上代码创建了任务ID,执行了TaskCreating方法,并将任务的操作权限赋给任务操作人。

Step10 在任务完成后,希望外部代码也会进行处理,所以在Step3中添加了一个code活动,用这个code活动来调用任务完成事件。在TaskActivity类中添加任务完成事件声明代码。

//任务完成后触发的事件

[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.

Visible)]

[BrowsableAttribute(true)] [CategoryAttribute(\杂项\

public event EventHandler TaskCompleted; 处理code活动的ExecuteCode事件,代码如下。

private void codeActivity1_ExecuteCode(object sender, EventArgs e) {

if (TaskCompleted != null) //触发任务完成后事件

TaskCompleted(this, new TaskEventArgs(this.TaskProperties)); }

最终的TaskActivity活动设计界面如图7-123所示。

图7-123 TaskActivity

TaskActivity完成后,多步审批流程的设计就变得简单了。下面将文档审批流程示例修改为2级审批:第一级由用户1审批,若用户1审批通过则给第二级用户2审批;若用户1拒绝,则结束流程。操作步骤如下。

Step1 添加第一级审批。从左边工具栏上拖曳TaskActivity到工作流设计器中,处理TaskActivity的TaskCreating事件,代码如下。

///

///分配一级审批任务 ///

///

private void taskActivity1_TaskCreating(object sender, TaskEventArgs e) {

e.TaskProperties.AssignedTo = \ e.TaskProperties.TaskType = 0;

e.TaskProperties.Title = \第一级用户审批\ }

以上代码指定了第一级的审批人为user1。处理TaskActivity的TaskCompleted事件,代码如下。 public bool task1ApprovalResult = false; public string task1Comments = \ ///

///一级审批任务完成后的处理 ///

///

private void taskActivity1_TaskCompleted(object sender, TaskEventArgs e) {

//一级审批任务完成后,将是否通过信息记录到task1ApprovalResult变量中 task1ApprovalResult = Convert.ToBoolean(e.TaskProperties.

ExtendedProperties[\

task1Comments = \ }

以上代码将第一级审批的结果和审批意见分别记录到task1ApprovalResult和task1Comments两个全局私有变量。

Step2 添加第二级审批。先拖曳IfElse活动到工作流设计器中,设置ifElseBranchActivity1的类型为“Declarative Rule Condition”,ConditionName为“task1Approved”,Expression为:

this.task1ApprovalResult == True

设计器如图7-124所示。

图7-124 ifElseBranchActivity1的条件设置

拖曳TaskActivity到ifElseBranchActivity1内,处理TaskCreating事件,代码如下。

///

///分配二级审批任务 ///

///

private void taskActivity2_TaskCreating(object sender, TaskEventArgs e) {

e.TaskProperties.AssignedTo = \ e.TaskProperties.TaskType = 0; e.TaskProperties.Title = \二级用户审批\ }

以上代码指定了第二级的审批人为user2。处理TaskActivity的TaskCompleted事件,代码如下。 public bool task2ApprovalResult = false; public string task2Comments =\ ///

///二级审批任务完成后的处理 ///

///

private void taskActivity2_TaskCompleted(object sender, TaskEventArgs e) {

//二级审批任务完成后,将是否通过信息记录到task2ApprovalResult变量中 task2ApprovalResult = Convert.ToBoolean(

e.TaskProperties.ExtendedProperties[\

string task2Comments = \

[\

string totalComments = \审批意见:\

审批意见:\

//更新内容审批状态

this.UpdateModerationStatus( task2ApprovalResult , totalComments ) ; }

以上代码按照审批结果修改文档的内容审核状态,UpdateModerationStatus用来更新文档状态,代码如下。

///

///改变内容审批状态 ///

///

private void UpdateModerationStatus(bool approval, string comments) {

SPModerationStatusType approvalState = approval ? SPModerationStatusType.Approved : SPModerationStatusType.Denied;

SPListItem item = this.workflowProperties.Item;

item[\修改审批状态字段 item[\修改审批批注字段 item.Update(); }

Step3 若第一级审批未通过,则需要设置文档状态为“已拒绝”。拖曳code活动到IfElse活动的第2个分支,处理其ExecuteCode事件,代码如下。

private void codeActivity1_ExecuteCode(object sender, EventArgs e) {

UpdateModerationStatus(false, this.task1Comments); //更新审批状态 }

以上代码直接设置文档审批状态为“已拒绝”。

编译项目后TaskActivity已经出现在左边的工具栏上,但是这时拖曳TaskActivity可能会出

错,遇到这种情况时首先部署工作流项目,确保将最新的DLL部署到GAC中,然后重启Visual Studio即可。

7.4.10 会签审批的实现

会签审批指的是多个人参与审批的,当审批通过数满足一定条件时,审批才

算通过。本节我们继续扩展文档审批流程,使其支持多个用户同时审批,只有所有用户都批准后才发布文档,只要有一个用户拒绝,则将文档状态改为“已拒绝”,并且结束会签。

使用replicator活动可以动态创建多个子活动。为简化代码,直接使用上一节开发的TaskActivity活动来实现单个任务的创建。具体操作步骤如下。

Step1 拖曳replicator活动到工作流设计器中,在replicator活动中添加一个TaskActitity活动,设计器效果如图7-125所示。

Step2 设置replicatorActivity1的“ExecutionType”属性为“Parallel”(并行审批),如图7-126所示。

replicatorActivity支持同时或顺序执行其动态创建的子活动,这里我们选择同时执行。

图7-125 添加replicator 图7-126 设置属性

Step3 在replicatorActivity 的Initialized事件中,可给其CurrentChildData集合属性添加多个数据,每个数据表示子活动。replicatorActivity的Initialized事件处理代码如下。

///

///设置子活动数据 ///

///

private void replicatorActivity1_Initialized(object sender, EventArgs e) {

foreach (Person person in this.GetConfigurationData().ApprovalUser) {

this.replicatorActivity1.CurrentChildData.Add(person.AccountId); } }

GetConfigurationData()方法用于从初始化表单中获取配置数据,为了避免序列化问题,这里没有用属性,而是用方法,代码如下。

//获取工作流配置数据,来自关联表单或初始化表单 private ConfigurationData GetConfigurationData() { //将配置数据反序列化为相应对象

XmlSerializer serializer = new XmlSerializer(typeof(ConfigurationData)); XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(

this.workflowProperties.InitiationData));

return (ConfigurationData)serializer.Deserialize(reader); }

Step4 处理replicatorActivity活动的ChildInitialized事件(子活动初始化),设置任务属性,代码如下。 private void replicatorActivity1_ChildInitialized(object sender, ReplicatorChildEventArgs e)

{

TaskActivity activity = e.Activity as TaskActivity;

activity.TaskProperties = new SPWorkflowTaskProperties();

activity.TaskProperties.AssignedTo = e.InstanceData.ToString(); //设置审批人 activity.TaskProperties.TaskType = 0; activity.TaskProperties.Title = \会签审批任务\ }

Step5 处理replicatorActivity活动的ChildCompleted事件(子活动执行完成,即审批任务完成),将任务数据保存到taskPropertiesList字段中,代码如下。

private List taskPropertiesList = new List (); ///

///任务完成处理 ///

///

private void replicatorActivity1_ChildCompleted(object sender,

ReplicatorChildEventArgs e)

{

TaskActivity activity = e.Activity as TaskActivity; taskPropertiesList.Add(activity.TaskProperties); }

Step6 指定replicatorActivity活动的UntilCondition为code condition,代码如下。 //replicatorActivity是否结束执行

private void Until(object sender, ConditionalEventArgs e) {

foreach (SPWorkflowTaskProperties taskProp in this.taskPropertiesList) {

//获取任务表单的approval字段

bool approval = Convert.ToBoolean(taskProp.ExtendedProperties

[\

if (approval == false) //若已经完成的任务中有一个审批未通过则结束任务 {

e.Result = true; return; } }

e.Result = this.taskPropertiesList.Count == this.replicatorActivity1.

CurrentChildData.Count;

}

以上代码检测已经完成的任务中是否有审批未通过的,若有则设置ConditionalEventArgs的Result属性为“false”,结束replicatorActivity活动的执行。

Step7 replicatorActivity活动执行完成后,需要按照会签结果设置文档的状态。拖曳一个code活动到replicatorActivity活动后面,处理其ExecuteCode事件,代码如下。

//审批任务完成后的处理

private void codeActivity1_ExecuteCode(object sender, EventArgs e) {

bool allPassed = true; string allComments = \

foreach (SPWorkflowTaskProperties taskProp in this.taskPropertiesList) {

bool approval = Convert.ToBoolean(taskProp.ExtendedProperties

[\

if (approval == false) {

allPassed = false; }

//累加审批意见 if (allComments != \ allComments += \

allComments += taskProp.AssignedTo + \

[\

}

this.UpdateModerationStatus(allPassed, allComments); //修改内容审批状态 }

以上代码检测已经完成的任务中是否有未通过的,然后调用UpdateModerationStatus方法设置文档审批状态。

7.4.11 工作流日志的记录

工作流日志的记录可以实现两个功能。

l SharePoint工作流代码出错的时候,监控页面的信息很少,为了便于查找错误,可以捕获关键代码抛出的异常,并将其记录到日志中。

l 通过日志,可以记录一些审批的信息。

SharePoint工作流日志的记录有以下两种方法。

l 通过workflowProperties属性调用CreateHistoryEvent方法,代码如下。 private void replicatorActivity1_ChildInitialized(object sender, ReplicatorChildEventArgs e) {

TaskActivity activity = e.Activity as TaskActivity;

activity.TaskProperties = new SPWorkflowTaskProperties(); activity.TaskProperties.AssignedTo = e.InstanceData.ToString(); activity.TaskProperties.TaskType = 0; activity.TaskProperties.Title = \会签审批任务\

//记录日志

this.workflowProperties.Workflow.CreateHistoryEvent((int)

SPWorkflowHistoryEventType.WorkflowError, 0,

this.workflowProperties.OriginatorUser, \会签任务创建\审批用户:\

e.InstanceData , \

}

l 从ActivityExecutionContext中获取到ISharePointService接口的实现,调用其LogToHistoryList方法,这种方法只适合于重载基类方法的时候使用,代码如下。

protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception) {

ISharePointService hostService = executionContext.GetService

();

if (hostService != null) { //记录日志

hostService.LogToHistoryList(this.workflowProperties.WorkflowId, SPWorkflowHistoryEventType.WorkflowError, 0, TimeSpan.MinValue, exception.Message, exception.StackTrace, \ }

return base.HandleFault(executionContext, exception); }

以上方法重载了工作流基类的HandleFault方法,将所有异常信息记录到日志中。

7.4.12 循环审批的实现

以上几节的实例都是标准的顺序工作流,任务依次创建,在实际的开发过程中我们经常要处理循环审批的情形,如图7-127所示。

图7-127 循环审批流程

循环审批需要采用While活动来实现。假设要把文档审批流程修改成如图7-127所示的流转逻辑,操作步骤如下。

Step1 设计提交人修改文档任务表单。审批人的审批表单继续使用

ApprovalForm.xsn,提交人修改文档时的任务表单需要重新设计,样式如图7-128所示。上级审批意见文本框用来显示审批人的审批意见,绑定到主数据源的“comments”域,默认值绑定到ItemMetadata辅助数据源的“comments”域中。表单设计好后,将其发布为“ReSubmitForm.xsn”。

Step2 修改工作流配置文件,将ReSubmitForm.xsn跟工作流进行关联。在feature.xml的ElementManifests节点下添加如下配置。

在workflow.xml的MetaData节点下添加如下配置。

urn:schemas-microsoft-com:office:infopath:ReSubmitForm: -myXSD-2008-10-02T19-07-06

Task1_FormURN节点的值通过表单的属性窗口获取。

图7-128 ReSubmitForm.xsn表单

Step3 添加While活动。拖曳While活动到工作流设计器,如图7-129所示。

图7-129 添加While活动

设置While活动的Condition为“NeedApproval”,代码如下。

private bool isFirstSubmit = true; private bool task1Result = false; ///

///循环条件 ///

///

private void NeedApproval(object sender, ConditionalEventArgs e) {

if (isFirstSubmit) //第一次提交的时候允许循环条件为true {

e.Result = true; }

else //审批任务完成后,若审批为通过,则继续循环 {

e.Result = !task1Result; } }

当第一次提交时(启动工作流),While活动执行条件为真,若审批任务为通过,则While需要继续执行,以便创建新的审批任务。

Step4 添加审批任务。拖曳Sequence活动到While活动内部。拖曳TaskActivity到Sequence活动内部,如图7-130所示。

图7-130 添加审批任务

处理taskActivity1的TaskCreating事件,代码如下。

///

///审批任务创建 ///

///

private void taskActivity1_TaskCreating(object sender, TaskEventArgs e) {

string approvalUser = this.GetConfigurationData().ApprovalUser[0].AccountId; e.TaskProperties.AssignedTo = approvalUser; //指定审批人 e.TaskProperties.Title = \审批任务\ e.TaskProperties.TaskType = 0; }

审批人从初始化表单配置数据中获取,TaskType指定为0,表示采用Task0_FormURN指定的表单。处理taskActivity1的TaskCompleted事件,代码如下。 private string task1Comments = \

private void taskActivity1_TaskCompleted(object sender, TaskEventArgs e) {

//记录审批结果

task1Result = Convert.ToBoolean(e.TaskProperties.ExtendedProperties

[\

task1Comments = \ isFirstSubmit = false; //记录日志

string approval = Convert.ToBoolean(e.TaskProperties.ExtendedProperties

[\批准\拒绝\

this.workflowProperties.Workflow.CreateHistoryEvent(

(int)SPWorkflowHistoryEventType.WorkflowComment, 0,

this.workflowProperties.OriginatorUser, approval, \审批用户:\

e.TaskProperties.AssignedTo + \审批时间:\审批意见:\ task1Comments, \

//更新文档内容审批状态

this.UpdateModerationStatus(task1Result, task1Comments); }

审批任务结束后,将审批结果和审批意见存放到task1Result和task1Comments字段中,并按照审批结果设置文档内容审批状态。

Step5 添加提交人修改任务。审批人审批未通过才给提交人分配修改任务,所以首先需要添加一个IfElse活动来判断是否审批人审批通过。

添加IfElse活动,并设置其第一个条件分支的规则条件为this.task1Result==false,如图7-131所示。

图7-131 添加IfElse活动

添加一个TaskActivity到IfElse活动的第一个分支,如图7-132所示。

图7-132 添加TaskActivity

处理taskActivity2的TaskCreating事件,代码如下。

///

///修改任务创建 ///

///

private void taskActivity2_TaskCreating(object sender, TaskEventArgs e) {

e.TaskProperties.AssignedTo = this.workflowProperties.Originator; e.TaskProperties.Title = \修改文档\

e.TaskProperties.TaskType = 1; //指定使用Task1_FormURN标识的表单 //设置表单辅助数据源值

e.TaskProperties.ExtendedProperties[\ }

以上代码创建新的任务,任务分配用户为流程的启动人,并且将审批意见同步到任务表单的辅助数据源。TaskType指定为1,表示采用Task1_FormURN指定的表单。

7.4.13 多状态工作流的实现

多状态工作流指的是在一个审批过程中存在多个审批状态(审批步骤)的工作流,每个状态可以按照条件跳转到其他任意状态,如图7-133所示。

图7-133 多状态工作流

WF支持状态机工作流,利用状态机工作流可以很容易地实现这种类型的流程,下一节将会具体讲述。SharePoint状态机工作流对每个状态单个审批任务支持得很好,但是如果某个审批状态需要多人审批,比如一个会签的场景,状态机工作流支持起来就很困难了。

WF提供了一个ConditionedActivityGroup活动,内部可以放置多个子活动,每个子活动都有一个是否执行的条件。利用ConditionedActivityGroup活动,可以采用顺序工作流实现多状态工作流。下面是具体的操作步骤。

Step1 设计任务表单。需要设计两个表单模板:提交人修改文档的表单我们直接采用上一节设计的ReSubmitForm.xsn。状态2和状态3审批任务的表单使用同一个表单,样式如图7-134所示,approvalState域是一个文本域,采用下拉列表,供审批人选择下一步的审批状态,表单发布为StateApprovalForm.xsn。

图7-134 StateApprovalForm.xsn

Step2 修改工作流配置文件。在feature.xml的ElementManifests节点下添加以下配置。

在workflow.xml的MetaData节点下添加以下配置。

urn:schemas-microsoft-com:office:infopath:StateApprovalForm:

-myXSD-2008-10-02T19-07-06

urn:schemas-microsoft-com:office:infopath:ReSubmitForm:

-myXSD-2008-10-02T19-07-06

Task0_FormURN为StateApprovalForm.xsn的ID,Task1_FormURN为ReSubmitForm.xsn的ID。

Step3 声明一个枚举类型,用来表示工作流的状态,代码如下。

///

///审批状态 ///

public enum ApprovalState {

//重新修改 ReSubmit, ///文档初审 PreApproval , //文档终审 Approval, //审批完成 Complete }

在工作流类中添加ApprovalState类型的字段,代码如下。 private ApprovalState approvalState = ApprovalState.PreApproval;

Step4 添加ConditionedActivityGroup活动,如图7-135所示。设置其UntilCondition的规则条件为:

this.approvalState == ApprovalState.Complete

当审批状态变成审批完成时,即结束ConditionedActivityGroup的执行。

图7-135 添加ConditionedActivityGroup活动

Step5 添加文档初审审批任务。在ConditionedActivityGroup中添加一个TaskActivity,名称改为preApprovalActivity,如图7-136所示。

图7-136 添加preApprovalActivity

设置preApprovalActivity的WhenCondition为条件规则,条件名称为IsPreApproval,表达式为:

this.approvalState == ApprovalState.PreApproval

这个规则指定当审批状态处于PreApproval时preApprovalActivity执行。

处理preApprovalActivity的TaskCreating事件,代码如下。

private void preApprovalActivity_TaskCreating(object sender, TaskEventArgs e) {

e.TaskProperties.Title = \文档初审\

e.TaskProperties.TaskType = 0; //指定使用Task0_FormURN标识的表单 e.TaskProperties.AssignedTo = \

}

以上代码将文档初审任务分配给user1用户,并指定TaskType为0,使审批任务使用StateApprovalForm.xsn表单。

处理preApprovalActivity的TaskCompleted事件,代码如下。

private void approvalActivity _TaskCompleted(object sender, TaskEventArgs e) {

////按照表单中approvalState域设置审批状态

this.approvalState = (ApprovalState)Enum.Parse(typeof(ApprovalState),

e.TaskProperties.ExtendedProperties[\

string comments = \ //记录日志

string approval = Convert.ToBoolean(e.TaskProperties.ExtendedProperties [\批准\拒绝\

this.workflowProperties.Workflow.CreateHistoryEvent( (int)SPWorkflowHistoryEventType.WorkflowComment, 0,

this.workflowProperties.OriginatorUser, this.approvalState.ToString(),

\审批用户:\审批时间:\审批意见:\

}

以上代码将审批表单中的审批状态域的值同步到工作流的approvalState字段,并且把审批意见域的值记录到工作流日志中。

Step6 添加文档终审审批任务。在ConditionedActivityGroup中添加一个TaskActivity,名称改为“approvalActivity”。设置approvalActivity的WhenCondition为条件规则,条件名称为“IsApproval”,表达式为:

this.approvalState == ApprovalState.Approval

这个规则指定当审批状态处于Approval时approvalActivity执行。处理preApprovalActivity的TaskCreating事件,代码如下。

private void approvalActivity_TaskCreating(object sender, TaskEventArgs e) {

e.TaskProperties.Title = \文档终审\

e.TaskProperties.TaskType = 0; //指定使用Task0_FormURN标识的表单 e.TaskProperties.AssignedTo = \ }

指定approvalActivity的TaskCompleted事件为approvalActivity_TaskCompleted。approvalActivity和preApprovalActivity两个任务活动的任务结束处理逻辑是一样的,所以使用同一个TaskCompleted事件处理函数。

Step7 添加文档修改任务。在ConditionedActivityGroup中添加一个

TaskActivity,名称改为“reSubmitActivity”。设置reSubmitActivity的WhenCondition为条件规则,条件名称为“IsApproval”,表达式为:

this.approvalState == ApprovalState.ReSubmit

本文来源:https://www.bwwdw.com/article/jfzp.html

Top