当你自定义控件时,你封装的控件属性,在访问时能访问但是却不能赋值给它,相当于指针指向了黑盒子,因此我们用Replicator控件来解决它。当然Replicator控件还有其他功能,其中对于工作流来说,审批过程中人员数的不确切这个问题也很容易的解决了。

Replicator控件

属性:

ExecutionType 指定activity的执行模式,是顺序还是状态。

InitialChildData 指定将包含复制器的初始子实例数据的集合。

条件:

UntilCondition 请指定导致复制器的内容activity停止执行的条件;

ChildInitialized 请指定初始化子活动的实例时要调用的方法。


在工作流中引用自定义控件的步骤:

一、OnWorkflowActivated 工作流启动方法 初始化工作流程。我们用FormContact类来解析初始化表单的数据,在microsoft.office.workflow.utility命名空间里。

转换初始化表单数据到一个哈希表

获得原始工作流的信息

设置复制器执行类型

使用内置的方法来解析出人

给每个联系人创建一个任务添加到replicator中,replicator创建列表中的每个子项

    准备replicator 的数据

源代码:

初始化工作流程private void OnWorkflowActivated(object sender, ExternalDataEventArgs e)
        
{
            
//Convert the initiation form data to a hashtable
            
//转换启动表单数据到一个哈希表
            this.initFormData = Form.XmlToHashtable(this.workflowProperties.InitiationData);

            
//Get the originator of the workflow
            
//获得原始工作流的信息
            this.workflowOriginator = Contact.FromPrincipal(this.workflowProperties.OriginatorUser);
            
this.workflowName = this.workflowProperties.Workflow.ParentAssociation.Name;
            
this.itemDisplayName = this.workflowProperties.Item.DisplayName;
            
//Set the replicator execution type
            
//设置复制器执行类型
            this.replicatorExecutionType = (this.initFormData["CreateTasksInSerial"as string== "true" ?
                ExecutionType.Sequence : ExecutionType.Parallel;

            
//Use the built-in methods to parse out the people
            
//使用内置的方法来解析出人
            Contact[] contacts = Contact.ToContacts((this.initFormData["Reviewers"as string), this.workflowProperties.Web);
            
            
//Determine if we want to expand groups that were entered into the form.
            
//定义我们想要扩充进入表单的组
            if ((this.initFormData["GroupTasks"as string== "false")
            
{
                
//Expand the groups (recursively)
                bool reachedMaxCount = false;
                contacts 
= Contact.ExpandGroups(this.workflowProperties.Web, contacts,
                    ApprovalWorkflowSample.MaxExpansionCount, 
out reachedMaxCount);
            }


            
//Add the data to the replicator so that we can generate a task for each contact.
            
//The replicator will create a child for each item in the list.
            
//给每个联系人创建一个任务添加到replicator中,replicator创建列表中的每个子项
            this.replicatorInitialChildData = new List<SPWorkflowTaskProperties>();
            
            
//Determine the due date of the task (if any)
            
//定义任务的日期
            DateTime dueDate = DateTime.MinValue;

            
//Due date from a serial approval workflow
            
//串行审批流程的日期
            if ((this.replicatorExecutionType == ExecutionType.Sequence) && (!string.IsNullOrEmpty(this.initFormData["TimePerTaskVal"as string)))
            
{
                dueDate 
= DateTime.Now.AddDays(Convert.ToInt32(this.initFormData["TimePerTaskVal"]));
            }

            
//Due date from a parallel approval workflow
            
//并行审批流程的日期
            else if ((this.replicatorExecutionType == ExecutionType.Parallel) && (!string.IsNullOrEmpty(this.initFormData["DueDate"as string)))
            
{
                dueDate 
= Convert.ToDateTime(this.initFormData["DueDate"]);
            }
            

            
//Prepare the replicator data
            
//准备 replicator 的数据
            string contactNames = "";

            
foreach (Contact contact in contacts)
            
{
                contactNames 
+= string.Format(" {0},", contact.DisplayName);

                SPWorkflowTaskProperties taskProperties 
= new SPWorkflowTaskProperties();
                taskProperties.AssignedTo 
= contact.LoginName;
                taskProperties.Description 
= string.IsNullOrEmpty(this.initFormData["Description"as string? "No instructions were provided." : this.initFormData["Description"as string;
                taskProperties.DueDate 
= dueDate;

                
this.replicatorInitialChildData.Add(taskProperties);
            }


            
//Trim the trailing ',' from the string
            
//用","分割字符串
            contactNames = contactNames.Substring(0, contactNames.Length - 1);

            
//Set the wss user id of the workflow originator
            
//设置原始工作流的用户ID
            int workflowOriginatorId = this.workflowOriginator.PrincipalID;

            
//Setup the "workflow started" history data
            
//设置workflow started的历史记录数据
            this.logWorkflowStartedHistoryActivity.HistoryDescription = string.Format("{0} was started.  Participants:{1}",
                
this.workflowName, contactNames);
            
this.logWorkflowStartedHistoryActivity.UserId = workflowOriginatorId;

            
//Setup the "workflow completed" history data
            
//设置workflow completed的历史记录数据
            this.logWorkflowCompletedHistoryActivity.HistoryDescription = string.Format("{0} was completed."this.workflowName);
            
this.logWorkflowCompletedHistoryActivity.HistoryOutcome = string.Format("{0} on {1} has successfully completed. All participants have completed their tasks.",
                
this.workflowName, this.itemDisplayName);
            
this.logWorkflowCompletedHistoryActivity.UserId = workflowOriginatorId;
        }

二、OnReplicatorChildInitializedInitialChildData方法: 指定将包含 复制器的初始子实例数据的集合。) :为每个复制器的子实例创建和初始化任务。

获取活动

设置任务

添加info表中的用户和检测与任务关联的用户

更新任务属性的值显示在infopath

设置其他值

设置created by用户 

源代码:

创建和初始化任务private void OnReplicatorChildInitialized(object sender, ReplicatorChildEventArgs e)
        
{
            
//Retrieve the activities
            
//获取活动
            WssTaskActivity task = e.Activity as WssTaskActivity;            
            task.createWssTask_TaskProperties1 
= (SPWorkflowTaskProperties)e.InstanceData;

            
//Setup the task
            
//设置任务
            task.TaskId = Guid.NewGuid();

            
//This does two things, adds the user to the infotable in wss (if possible) and 
            
//allows us to check for users that can't be assigned a task.
            
//添加info表中的用户和检测与任务关联的用户
            Contact contact = Contact.FromName(task.createWssTask_TaskProperties1.AssignedTo, this.workflowProperties.Web);
            SPPrincipal contactPrincipal 
= contact.GetPrincipal(this.workflowProperties.Web);

            
if ((contactPrincipal == null|| (contactPrincipal.ID == -1))
            
{
                
//We can't assign the task to this principal - let's try the workflow owner
                task.createWssTask_TaskProperties1.AssignedTo = this.workflowOriginator.LoginName;
                task.createWssTask_TaskProperties1.Title 
= string.Format("Please approve {0} (external participant)"this.itemDisplayName);
                task.createWssTask_TaskProperties1.OnBehalfEmail 
= contact.EmailAddress;
                task.createWssTask_TaskProperties1.OnBehalfReason 
= "This user does not have access to this Windows SharePoint Server site.";
                task.TaskAssignedTo 
= this.workflowOriginator;
            }

            
else
            
{
                
//Normal task
                task.createWssTask_TaskProperties1.Title = string.Format("Please approve {0}"this.itemDisplayName);
                task.TaskAssignedTo 
= contact;
            }


            
// update the unescaped description text which is displayed inside infopath
            
//更新description属性的值显示在infopath中
            task.createWssTask_TaskProperties1.ExtendedProperties["BodyText"= SPHttpUtility.HtmlDecode(task.createWssTask_TaskProperties1.Description);

            
//Set the remaining values
            
//设置其他值
            task.createWssTask_TaskProperties1.PercentComplete = 0;
            task.createWssTask_TaskProperties1.SendEmailNotification 
= true;
            task.createWssTask_TaskProperties1.StartDate 
= DateTime.Now;
            task.createWssTask_TaskProperties1.TaskType 
= Convert.ToInt32(this.initFormData["DefaultTaskType"]);
            
            
//Set the "created by" user
            
//设置created by用户
            if (task.TaskCreatedBy == null)
            
{
                task.TaskCreatedBy 
= this.workflowOriginator;
            }

        }

三、IsReplicatorDone UntilCondition 请指定导致复制器的内容activity停止执行的条件;

):判断复制器是否已完成任务的条件。

源代码:

        private void IsReplicatorDone(object sender, ConditionalEventArgs e)
        
{
            
//Have all the replicator children completed?
            e.Result = this.taskReplicator1.AllChildrenComplete;
        }

四、IsTaskCompleted(自定义控件的onTaskChanged的自定义方法isTaskCompleted: 任务修改了反射到自定义控件的IsTaskCompleted事件中。IsTaskCompleted事件参数TaskEventArgs包含了SPWorkflowTaskProperties (AfterProperties)属性,该属性是任务修改时存储修改时的新值。

获得任务数据

获得审批该活动的用户

获得任务结果——#@TaskStatus属性中显示完成

判断结果是否取消流程

判断结果是否任务已完成

源代码:
        private void IsTaskCompleted(object sender, TaskEventArgs e)
        
{
            
//Get the task data
            
//获得任务数据
            WssTaskActivity task = sender as WssTaskActivity;

            
//Get the name of the user who performed this action
            
//获取活动的当前用户
            Contact contact = Contact.FromName(e.Executor, this.workflowProperties.Web);

            
//Get the task result - # and @ in the "TaskStatus" field indicate a completion
            
//获得任务结果-#和@在TaskStatus属性中显示完成
            string taskResult = e.AfterProperties.ExtendedProperties["TaskStatus"as string;

            
bool isTaskRejected = (taskResult == "@");
            e.Result 
= isTaskRejected || (taskResult == "#");                       

            
//Single rejection rejects the entire workflow
            
//取消流程
            if (isTaskRejected)
            
{
                
this.isWorkflowRejected = true;
            }


            
//Is the task completed
            
//任务是否完成
            if (e.Result)
            
{
                task.TaskChangedBy 
= contact;
                task.TaskCompletedBy 
= contact;
                task.completeWssTask_TaskOutcome1 
= isTaskRejected ? string.Format("Task rejected by {0}", contact.DisplayName) : 
                    
string.Format("Task approved by {0}", contact.DisplayName);                
            }

        }

五、OnTaskDeleted (自定义控件onTaskDeletedInvoked方法):删除任务事件。

获得任务数据

获得审批该活动的用户

设置友好的名称

拒绝工作流

源代码:

OnTaskDeletedprivate void OnTaskDeleted(object sender, TaskEventArgs e)
        
{
            
//Get the task

            WssTaskActivity task 
= sender as WssTaskActivity;

            
//Get the name of the user who performed this action
            
//获得审批该活动的用户
            Contact contact = Contact.FromName(e.Executor, this.workflowProperties.Web);

            
//Set the friendly name
            
//设置友好的名称
            task.TaskDeletedBy = contact;

            
//Reject the workflow
            
//拒绝工作流
            this.isWorkflowRejected = true;
        }


posted on 2008-06-01 12:38  晃晃悠悠  阅读(295)  评论(0)    收藏  举报