• 采用Visual Studio 2008 开发工作流模板(四)


    工作流模板的初始化表单

    初始化表单是启动流程时调用的表单,供启动流程的用户填写一些数据。在流程代码中,可以通过workflowProperties字段的InitiationData属性获取到初始化表单的数据。InitiationData放置的是初始化的xml格式的数据。

    若存在关联表单,初始化表单的数据源架构必须跟关联表单一致,关联表单的数据将作为初始化表单的默认值。为了保持架构一致,初始化表单可以直接将关联表单另存为一份副本进行修改。

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

    1.设计表单模板

    Step1  将AssociationForm.xsn另存为InitiationForm.xsn。

    Step2  修改表单,如图1所示。

    1 InitiationForm表单样式

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

    2.修改配置文件

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

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

    <ElementFile Location="InitiationForm.xsn" />

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

    InstantiationUrl="_layouts/IniWrkflIP.aspx"

    MetaData节点下添加如下属性。

    <Instantiation_FormURN>urn:schemas-microsoft-com:office:infopath:InitiationForm:

    -myXSD-2008-10-04T07-45-17</Instantiation_FormURN>

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

    3.修改工作流代码

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

    private ConfigurationData _ConfigurationData;

            ///<summary>

            ///配置数据

            ///</summary>

            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类型。

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

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

    Step1  新建一个活动,名称为"TaskActivity"   

    Step2  拖曳createTaskonTaskChangedcompleteTask 3个活动到设计器中。

    Step3  拖曳一个code活动到设计器中,如图2所示。

    2  TaskActivity

    Step4  设置createTaskonTaskChangedcompleteTaskcorrelationToken属性为"taskToken"

    Step5  createTaskonTaskChangedCompleteTaskTaskId绑定到活动类的taskId字段,将createTaskSpecialPermission属性绑定到活动类的specialPermission字段。

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

    3 绑定到活动类的TaskProperties属性

    Step7  onTaskChangedBeforePropertiesAfterProperties属性均绑定到活动类的TaskProperties属性。

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

    ///<summary>

        ///任务事件参数

        ///</summary>

        public class TaskEventArgs : EventArgs

        {

            ///<summary>

            ///任务属性

            ///</summary>

            public readonly SPWorkflowTaskProperties TaskProperties;

            public TaskEventArgs(SPWorkflowTaskProperties taskProperties)

            {

                TaskProperties = taskProperties;

            }

        }

    TaskActivity类中添加事件声明代码。

    //任务创建前触发的事件       

    [DesignerSerializationVisibilityAttribute(
                 DesignerSerializationVisibility.Visible)]

     [BrowsableAttribute(true)]

     [CategoryAttribute("杂项")]

     public event EventHandler<EventArgs> TaskCreating;

    Step9  处理createTaskMethodInvoking事件,代码如下。

    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<EventArgs> TaskCompleted;

    处理code活动的ExecuteCode事件,代码如下。

    private void codeActivity1_ExecuteCode(object sender, EventArgs e)

            {

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

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

            } 

    最终的TaskActivity活动设计界面如图4所示。

    4 TaskActivity

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

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

    ///<summary>

            ///分配一级审批任务

            ///</summary>   

            ///<param name="sender"></param>

            ///<param name="e"></param>

            private void taskActivity1_TaskCreating(object sender, TaskEventArgs e)

            {

                e.TaskProperties.AssignedTo = "codeart\\user1";

                e.TaskProperties.TaskType = 0;

                e.TaskProperties.Title = "第一级用户审批";

            }

    以上代码指定了第一级的审批人为user1。处理TaskActivityTaskCompleted事件,代码如下。

           public bool task1ApprovalResult = false;

            public string task1Comments = "";

            ///<summary>

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

            ///</summary>

            ///<param name="sender"></param>

            ///<param name="e"></param>

            private void taskActivity1_TaskCompleted(object sender, TaskEventArgs e)

            {

               //一级审批任务完成后,将是否通过信息记录到task1ApprovalResult变量中

                task1ApprovalResult = Convert.ToBoolean(e.TaskProperties.

    ExtendedProperties["approval"]);

                task1Comments = ""+e.TaskProperties.ExtendedProperties["comments"];

            }

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

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

    this.task1ApprovalResult == True

    设计器如图5所示。

    5  ifElseBranchActivity1的条件设置

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

            ///<summary>

            ///分配二级审批任务

            ///</summary>

            ///<param name="sender"></param>

            ///<param name="e"></param>

            private void taskActivity2_TaskCreating(object sender, TaskEventArgs e)

            {

                e.TaskProperties.AssignedTo = "codeart\\user2";

                e.TaskProperties.TaskType = 0;

                e.TaskProperties.Title = "二级用户审批";

            }

    以上代码指定了第二级的审批人为user2。处理TaskActivityTaskCompleted事件,代码如下。

    public bool task2ApprovalResult = false;

            public string task2Comments ="" ;

            ///<summary>

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

            ///</summary>

            ///<param name="sender"></param>

            ///<param name="e"></param>

            private void taskActivity2_TaskCompleted(object sender, TaskEventArgs e)

            {

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

                task2ApprovalResult = Convert.ToBoolean(
    e.TaskProperties.ExtendedProperties["approval"]);

                string task2Comments =  ""+e.TaskProperties.ExtendedProperties

    ["comments"];

                string totalComments = "user1 审批意见:" + task1Comments + "\n user2
    审批意见:" + task2ApprovalResult;

              //更新内容审批状态

                this.UpdateModerationStatus( task2ApprovalResult , totalComments ) ;

            }

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

        ///<summary>

            ///改变内容审批状态

            ///</summary>

            ///<param name="approval"></param>

            ///<param name="comments"></param>

            private void UpdateModerationStatus(bool approval, string comments)

            {

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

                SPListItem item = this.workflowProperties.Item;

                item["_ModerationStatus"] = (int)approvalState; //修改审批状态字段

                item["_ModerationComments"] = comments; //修改审批批注字段

                item.Update();

            }

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

    private void codeActivity1_ExecuteCode(object sender, EventArgs e)

            {

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

            }

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

    会签审批的实现

    会签审批指的是多个人参与审批的,当审批通过数满足一定条件时,审批才算通过。本节我们继续扩展文档审批流程,使其支持多个用户同时审批,只有所有用户都批准后才发布文档,只要有一个用户拒绝,则将文档状态改为"已拒绝",并且结束会签。

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

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

    Step2  设置replicatorActivity1"ExecutionType"属性为"Parallel"(并行审批),如图7所示。

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

    6添加replicator

    7设置属性

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

            ///<summary>

            ///设置子活动数据

            ///</summary>   

            ///<param name="sender"></param>

            ///<param name="e"></param>   

            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<SPWorkflowTaskProperties> taskPropertiesList = new List

    <SPWorkflowTaskProperties>();

            ///<summary>

            ///任务完成处理

            ///</summary>

            ///<param name="sender"></param>

            ///<param name="e"></param>

            private void replicatorActivity1_ChildCompleted(object sender,

    ReplicatorChildEventArgs e)

            {

                TaskActivity activity = e.Activity as TaskActivity;

                taskPropertiesList.Add(activity.TaskProperties);

            }

    Step6  指定replicatorActivity活动的UntilConditioncode condition,代码如下。

    //replicatorActivity是否结束执行

    private void Until(object sender, ConditionalEventArgs e)

            {

                foreach (SPWorkflowTaskProperties taskProp in this.taskPropertiesList)

                { 

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

                    bool approval = Convert.ToBoolean(taskProp.ExtendedProperties

    ["approval"]);

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

                    {

                        e.Result = true;

                        return;

                    }

                }

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

    CurrentChildData.Count;

            }

    以上代码检测已经完成的任务中是否有审批未通过的,若有则设置ConditionalEventArgsResult属性为"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

    ["approval"]);

                    if (approval == false)

                    {

                        allPassed = false;

                    }

                    //累加审批意见

                    if (allComments != "")

                        allComments += "\n";

              allComments += taskProp.AssignedTo + ":" + taskProp.ExtendedProperties

    ["comments"];

                }

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

            }

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

    转载:http://book.csdn.net/bookfiles/936/10093629438.shtml

  • 相关阅读:
    【资料整理】面向对象
    【资料整理】函数(方法)
    【资料整理】数组
    【资料整理】循环、判断、三元表达式
    【资料整理】类型转换、运算符
    【资料整理】c#基础
    线性表的链式表示和实现
    线性表
    PAT 乙级1062最简分数
    HDU 1027(全排列)
  • 原文地址:https://www.cnblogs.com/KimhillZhang/p/1530012.html
Copyright © 2020-2023  润新知