当你自定义控件时,你封装的控件属性,在访问时能访问但是却不能赋值给它,相当于指针指向了黑盒子,因此我们用Replicator控件来解决它。当然Replicator控件还有其他功能。。。。。。。。。。。。。。
    
当你自定义控件时,你封装的控件属性,在访问时能访问但是却不能赋值给它,相当于指针指向了黑盒子,因此我们用
Replicator控件来解决它。当然
Replicator控件还有其他功能,其中对于工作流来说,审批过程中人员数的不确切这个问题也很容易的解决了。
Replicator控件
属性:
ExecutionType 指定activity的执行模式,是顺序还是状态。
InitialChildData 指定将包含复制器的初始子实例数据的集合。
条件:
UntilCondition 请指定导致复制器的内容activity停止执行的条件;
ChildInitialized 请指定初始化子活动的实例时要调用的方法。
在工作流中引用自定义控件的步骤:
一、OnWorkflowActivated 工作流启动方法 :初始化工作流程。我们用Form和Contact类来解析初始化表单的数据,在microsoft.office.workflow.utility命名空间里。
转换初始化表单数据到一个哈希表
获得原始工作流的信息
设置复制器执行类型
使用内置的方法来解析出人
给每个联系人创建一个任务添加到replicator中,replicator创建列表中的每个子项
    准备replicator 的数据
源代码:

 初始化工作流程
初始化工作流程
 private void OnWorkflowActivated(object sender, ExternalDataEventArgs e)
        private void OnWorkflowActivated(object sender, ExternalDataEventArgs e)

 
         {
{
 //Convert the initiation form data to a hashtable
            //Convert the initiation form data to a hashtable
 //转换启动表单数据到一个哈希表
            //转换启动表单数据到一个哈希表
 this.initFormData = Form.XmlToHashtable(this.workflowProperties.InitiationData);
            this.initFormData = Form.XmlToHashtable(this.workflowProperties.InitiationData);

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

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

 
             {
{
 //Expand the groups (recursively)
                //Expand the groups (recursively)
 bool reachedMaxCount = false;
                bool reachedMaxCount = false;
 contacts = Contact.ExpandGroups(this.workflowProperties.Web, contacts,
                contacts = Contact.ExpandGroups(this.workflowProperties.Web, contacts,
 ApprovalWorkflowSample.MaxExpansionCount, out reachedMaxCount);
                    ApprovalWorkflowSample.MaxExpansionCount, out reachedMaxCount);
 }
            }

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

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

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

 
             {
{
 dueDate = Convert.ToDateTime(this.initFormData["DueDate"]);
                dueDate = Convert.ToDateTime(this.initFormData["DueDate"]);
 }
            }            

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

 foreach (Contact contact in contacts)
            foreach (Contact contact in contacts)

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

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

 this.replicatorInitialChildData.Add(taskProperties);
                this.replicatorInitialChildData.Add(taskProperties);
 }
            }

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

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

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

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

二、OnReplicatorChildInitialized(InitialChildData方法: 指定将包含 复制器的初始子实例数据的集合。) :为每个复制器的子实例创建和初始化任务。
获取活动
设置任务
添加info表中的用户和检测与任务关联的用户
更新任务属性的值显示在infopath中
设置其他值
设置created by用户  
源代码:

 创建和初始化任务
创建和初始化任务
 private void OnReplicatorChildInitialized(object sender, ReplicatorChildEventArgs e)
        private void OnReplicatorChildInitialized(object sender, ReplicatorChildEventArgs e)

 
         {
{
 //Retrieve the activities
            //Retrieve the activities
 //获取活动
            //获取活动
 WssTaskActivity task = e.Activity as WssTaskActivity;
            WssTaskActivity task = e.Activity as WssTaskActivity;            
 task.createWssTask_TaskProperties1 = (SPWorkflowTaskProperties)e.InstanceData;
            task.createWssTask_TaskProperties1 = (SPWorkflowTaskProperties)e.InstanceData;

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

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

 if ((contactPrincipal == null) || (contactPrincipal.ID == -1))
            if ((contactPrincipal == null) || (contactPrincipal.ID == -1))

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

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

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

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

 
             {
{
 task.TaskCreatedBy = this.workflowOriginator;
                task.TaskCreatedBy = this.workflowOriginator;
 }
            }
 }
        }

三、IsReplicatorDone (UntilCondition 请指定导致复制器的内容activity停止执行的条件;
):判断复制器是否已完成任务的条件。
源代码:
 private void IsReplicatorDone(object sender, ConditionalEventArgs e)
        private void IsReplicatorDone(object sender, ConditionalEventArgs e)

 
         {
{
 //Have all the replicator children completed?
            //Have all the replicator children completed?
 e.Result = this.taskReplicator1.AllChildrenComplete;
            e.Result = this.taskReplicator1.AllChildrenComplete;
 }
        }

四、IsTaskCompleted(自定义控件的onTaskChanged的自定义方法isTaskCompleted): 任务修改了反射到自定义控件的IsTaskCompleted事件中。IsTaskCompleted事件参数TaskEventArgs包含了SPWorkflowTaskProperties (AfterProperties)属性,该属性是任务修改时存储修改时的新值。
获得任务数据
获得审批该活动的用户
获得任务结果——#和@在TaskStatus属性中显示完成
判断结果是否取消流程
判断结果是否任务已完成
源代码:
 private void IsTaskCompleted(object sender, TaskEventArgs e)
        private void IsTaskCompleted(object sender, TaskEventArgs e)

 
         {
{
 //Get the task data
            //Get the task data
 //获得任务数据
            //获得任务数据
 WssTaskActivity task = sender as WssTaskActivity;
            WssTaskActivity task = sender as WssTaskActivity;

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

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

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

 //Single rejection rejects the entire workflow
            //Single rejection rejects the entire workflow
 //取消流程
            //取消流程
 if (isTaskRejected)
            if (isTaskRejected)

 
             {
{
 this.isWorkflowRejected = true;
                this.isWorkflowRejected = true;
 }
            }

 //Is the task completed
            //Is the task completed
 //任务是否完成
            //任务是否完成
 if (e.Result)
            if (e.Result)

 
             {
{
 task.TaskChangedBy = contact;
                task.TaskChangedBy = contact;
 task.TaskCompletedBy = contact;
                task.TaskCompletedBy = contact;
 task.completeWssTask_TaskOutcome1 = isTaskRejected ? string.Format("Task rejected by {0}", contact.DisplayName) :
                task.completeWssTask_TaskOutcome1 = isTaskRejected ? string.Format("Task rejected by {0}", contact.DisplayName) : 
 string.Format("Task approved by {0}", contact.DisplayName);
                    string.Format("Task approved by {0}", contact.DisplayName);                
 }
            }
 }
        }

五、OnTaskDeleted (自定义控件onTaskDeleted的Invoked方法):删除任务事件。
获得任务数据
获得审批该活动的用户
设置友好的名称
拒绝工作流
源代码:

 OnTaskDeleted
OnTaskDeleted
 private void OnTaskDeleted(object sender, TaskEventArgs e)
        private void OnTaskDeleted(object sender, TaskEventArgs e)

 
         {
{
 //Get the task
            //Get the task

 WssTaskActivity task = sender as WssTaskActivity;
            WssTaskActivity task = sender as WssTaskActivity;

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

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

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