1、添加子问题类型:紧急发布,并关联问题类型方案: Test Apply Type Scheme
2、添加工作流:Patch workflow
3、添加工作流方案:sub patch workflow scheme,把工作流patch workflow加入方案
4、进项目修改工作流方案,添加新的工作流:patch workflow,使得项目的工作流方案 Test Apply Workflow Scheme 下有两个工作流,不同工作流关联不同的问题类型配置完后如下:
子任务独立界面:
1、添加界面:sub patch screen
2、添加界面方案:sub patch screen scheme
3、在原来的问题界面方案: Test Apply Type Screen Scheme ,配置如下:
工作流是现在OA中的一个部分,就是可以实现多人协同办公,多人共同完成一项工作,添加时就在OA中新建就可以了,你可以让某些人看到某些人来办这个工作。而且可以规定按怎么样的流程往下一步步的走,而且每个人在上面的办理情况都会有所体现!右击本地服务器上的“数据库”节点,然后选择“新建数据库”。 将新数据库命名为 WF45GettingStartedTutorial,接受所有其他值,然后选择“确定”。 注意 在创建数据库前,确保您在本地服务器上具有创建数据库权限。 从“文件”菜单中选择“打开”,然后单击“文件”。 浏览到:C:\Windows\Microsoft.NET\Framework\4.0.30319\sql\en 以下文件夹 选择以下两个文件,然后单击“打开”。 SqlWorkflowInstanceStoreLogic.sql SqlWorkflowInstanceStoreSchema.sql 从”窗口“菜单选择“SqlWorkflowInstanceStoreSchema.sql”。 从“查询”菜单确保“WF45GettingStartedTutorial”选择“可用数据库”下拉菜单,然后选择“执行”。 从”窗口“菜单选择“SqlWorkflowInstanceStoreLogic.sql”。 从“查询”菜单确保“WF45GettingStartedTutorial”选择“可用数据库”下拉菜单,然后选择“执行”。 注意 按正确的顺序执行前面的两个步骤,这一点非常重要。 如果不按顺序执行查询,系统会发生错误,并且持久性数据库会配置不正确。 向DurableInstancing 程序集中添加引用 在“解决方案资源管理器”中右击“NumberGuessWorkflowHost”,然后选择“添加引用”。 在“添加引用”列表中选择“程序集”,并在“搜索程序集”框中键入 DurableInstancing。 这会筛选程序集,并使所需引用更便于选择。 从“搜索结果”列表检查旁边的复选框“System.Activities.DurableInstancing”和“System.Runtime.DurableInstancing”,然后单击“确定”。 创建工作流宿主窗体注意 此过程中的步骤描述了如何手动添加和配置窗体。 如果需要,可以下载教程的解决方案文件,并将完成的窗体添加至项目中。 下载教程文件,请参见 Windows Workflow Foundation (WF45) - 入门教程 。 文件下载后,在“解决方案资源管理器”中右击“NumberGuessWorkflowHost”,并选择“添加”,“现有项”。 浏览至项目文件中的 Asset 文件夹,并选择 “WorkflowHostForm”。 在“解决方案资源管理器”中右击“NumberGuessWorkflowHost”并选择“添加”,“新项目”。 在“已安装”模板列表中,选择“Windows 窗体”,在“名称”框中键入WorkflowHostForm,并单击“添加”。 配置窗体上的以下属性。 属性 Value FormBorderStyle FixedSingle MaximizeBox False 大小 400, 420 按指定的顺序将以下控件添加到窗体中,并按照需要配置属性。 控制 属性 Value 按钮 名称 btnNew 位置 13, 13 大小 75, 23 Text 新游戏 标签 位置 94, 18 Text 猜测一个数字从 1 至 ComboBox 名称 cboRange DropDownStyle DropDownList 项 10 100 1000 位置 228, 12 大小 143, 21 标签 位置 13, 43 Text 工作流类型 ComboBox 名称 cboType DropDownStyle DropDownList 项 StateMachineNumberGuessWorkflow FlowchartNumberGuessWorkflow SequentialNumberGuessWorkflow 位置 94, 40 大小 277, 21 标签 名称 lblVersion 位置 13, 362 Text 工作流版本 GroupBox 位置 13, 84 大小 358, 270 Text Game 注意 以下控件包含在“GroupBox”中。 在将它们添加至窗体时,将它们放到“GroupBox”上。 标签 位置 7, 20 Text 工作流实例 Id ComboBox 名称 cboInstanceId DropDownStyle DropDownList 位置 121, 17 大小 231, 21 标签 位置 7, 47 Text 猜测TextBox 名称 txtGuess 位置 50, 44 大小 65, 20 按钮 名称 btnGuess 位置 121, 42 大小 75, 23 Text 转至按钮 名称 btnQuit 位置 277, 42 大小 75, 23 Text 退出TextBox 名称 txtStatus 位置 10, 73 Multiline True ReadOnly True ScrollBars 垂直 大小 342, 191 将窗体的“AcceptButton”属性设置为“btnGuess”。 下面的示例阐释已完成的窗体。 添加窗体的属性和帮助器方法 本节的步骤将属性和帮助器添加至窗体类,此窗体类将配置窗体的 UI,以支持运行和继续执行数字猜测工作流。 在“解决方案资源管理器”中右击“WorkflowHostForm”并选择“查看代码”。 添加以下 using(或 Imports)语句和另一些using(或 Imports)语句到文件的顶部。 using System.Activities.DurableInstancingusing System.Activitiesusing System.Data.SqlClientusing System.IO将以下成员声明添加到“WorkflowHostForm”类中。 const string connectionString = "Server=.\\SQLEXPRESSInitial Catalog=WF45GettingStartedTutorialIntegrated Security=SSPI"SqlWorkflowInstanceStore storebool WorkflowStarting注意 如果您的连接字符串不同,请更新 connectionString 引用数据库。 将WorkflowInstanceId 属性添加到 WorkflowFormHost 类中。 public Guid WorkflowInstanceId { get { return cboInstanceId.SelectedIndex == -1 ? Guid.Empty : (Guid)cboInstanceId.SelectedItem} }cboInstanceId 组合框显示保留的工作流实例 ID 列表,且 WorkflowInstanceId 属性返回当前选定的工作流。 为窗体 Load 事件添加下面的处理程序。 若要添加处理程序,则切换到窗体的“设计视图”,单击“属性”窗口顶部的“事件”图标,并双击“加载”。 private void WorkflowHostForm_Load(object sender, EventArgs e) { // Initialize the store and configure it so that it can be used for // multiple WorkflowApplication instances. store = new SqlWorkflowInstanceStore(connectionString)WorkflowApplication.CreateDefaultInstanceOwner(store, null, WorkflowIdentityFilter.Any)// Set default ComboBox selections. cboRange.SelectedIndex = 0cboType.SelectedIndex = 0ListPersistedWorkflows()} 在窗体加载时,SqlWorkflowInstanceStore 进行配置,范围和工作流类型组合框将会设置为默认值,且保留的工作流实例将添加到 cboInstanceIds 中。 为cboInstanceId 添加以下 SelectedIndexChanged 处理程序。 若要添加处理程序,则切换到窗体的“设计视图”,选择 cboInstanceId 组合框,单击“属性”窗口顶部的“事件”图标,并双击“SelectedIndexChanged”。 无论用户何时使用组合框选择工作流,此处理程序均更新状态窗口。 private void cboInstanceId_SelectedIndexChanged(object sender, EventArgs e) { if (cboInstanceId.SelectedItem == null) { return} // Clear the status window. txtStatus.Clear()// Get the workflow version and display it. // If the workflow is just starting then this info will not // be available in the persistence store so do not try and retrieve it. if (!WorkflowStarting) { WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(this.WorkflowInstanceId, store)lblVersion.Text = WorkflowVersionMap.GetIdentityDescription(instance.DefinitionIdentity)// Unload the instance. instance.Abandon()} } 将下面的 ListPersistedWorkflows 方法添加到窗体类中。 private void ListPersistedWorkflows() { using (SqlConnection localCon = new SqlConnection(connectionString)) { string localCmd = "Select [InstanceId] from [System.Activities.DurableInstancing].[Instances] Order By [CreationTime]"SqlCommand cmd = localCon.CreateCommand()cmd.CommandText = localCmdlocalCon.Open()using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection)) { while (reader.Read()) { // Get the InstanceId of the persisted Workflow Guid id = Guid.Parse(reader[0].ToString())cboInstanceId.Items.Add(id)} } } }ListPersistedWorkflows 查询保留的工作流实例的实例存储区,并将实例 ID 添加到 cboInstanceId 组合框中。 将下面的 UpdateStatus 方法和对应的委托添加到窗体类中。 此方法使用当前正在运行的工作流的状态来更新窗体上的状态窗口。 private delegate void UpdateStatusDelegate(string msg)public void UpdateStatus(string msg) { // We may be on a different thread so we need to // make this call using BeginInvoke. if (txtStatus.InvokeRequired) { BeginInvoke(new UpdateStatusDelegate(UpdateStatus), msg)} else { if (!msg.EndsWith("\r\n")) { msg += "\r\n"} txtStatus.Text += msgtxtStatus.SelectionStart = txtStatus.Text.LengthtxtStatus.ScrollToCaret()} } 将下面的 GameOver 方法和对应的委托添加到窗体类中。 当工作流完成时,此方法通过从“工作流实例 ID”组合框中删除完成的工作流实例 ID 来更新窗体 UI。 private delegate void GameOverDelegate()private void GameOver() { if (this.InvokeRequired) { BeginInvoke(new GameOverDelegate(GameOver))} else { // Remove this instance from the combo box cboInstanceId.Items.Remove(cboInstanceId.SelectedItem)cboInstanceId.SelectedItem = null} }配置实例存储区、工作流生命周期处理程序和扩展 向窗体类添加 ConfigureWorkflowApplication 方法。 private void ConfigureWorkflowApplication(WorkflowApplication wfApp) { } 此方法配置 WorkflowApplication,添加所需扩展,并添加工作流生命周期事件的处理程序。 在ConfigureWorkflowApplication中,为 WorkflowApplication 指定SqlWorkflowInstanceStore。 // Configure the persistence store. wfApp.InstanceStore = store接下来创建 StringWriter 实例,并将它添加到 WorkflowApplication 的Extensions 集合中。 在将StringWriter 添加到扩展中时,它会捕获所有 WriteLine 活动输出 。在工作流进入空闲状态时,可从 StringWriter 中提取 WriteLine 输出,并显示在窗体上。 // Add a StringWriter to the extensions. This captures the output // from the WriteLine activities so we can display it in the form. StringWriter sw = new StringWriter()wfApp.Extensions.Add(sw)为Completed 事件添加以下处理程序。 在工作流成功完成时,执行猜测数字的轮数会显示到状态窗口。 如果工作流终止,系统会显示导致终止的异常信息。 在处理程序结束时,系统会调用 GameOver 方法,此方法从工作流列表中删除完成的工作流。 wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e) { if (e.CompletionState == ActivityInstanceState.Faulted) { UpdateStatus(string.Format("Workflow Terminated. Exception: {0}\r\n{1}", e.TerminationException.GetType().FullName, e.TerminationException.Message))} else if (e.CompletionState == ActivityInstanceState.Canceled) { UpdateStatus("Workflow Canceled.")} else { int Turns = Convert.ToInt32(e.Outputs["Turns"])UpdateStatus(string.Format("Congratulations, you guessed the number in {0} turns.", Turns))} GameOver()}添加以下 Aborted 和OnUnhandledException 处理程序。 GameOver 方法不从 Aborted 处理程序中调用,因为在工作流实例中止时,它并未终止,且以后可能继续执行实例。 wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e) { UpdateStatus(string.Format("Workflow Aborted. Exception: {0}\r\n{1}", e.Reason.GetType().FullName, e.Reason.Message))}wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e) { UpdateStatus(string.Format("Unhandled Exception: {0}\r\n{1}", e.UnhandledException.GetType().FullName, e.UnhandledException.Message))GameOver()return UnhandledExceptionAction.Terminate}添加以下 PersistableIdle 处理程序。 此处理程序检索所添加的 StringWriter 扩展,从 WriteLine 活动中提取输出,并将它显示在状态窗口中。 wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) { // Send the current WriteLine outputs to the status window. var writers = e.GetInstanceExtensions<StringWriter>()foreach (var writer in writers) { UpdateStatus(writer.ToString())} return PersistableIdleAction.Unload}PersistableIdleAction 枚举有三个值: None、 Persist 和 Unload。 Persist 会导致工作流保留,但不会导致工作流卸载。 Unload 会导致工作流保留并卸载。 以下示例是完整的 ConfigureWorkflowApplication 方法。 private void ConfigureWorkflowApplication(WorkflowApplication wfApp) { // Configure the persistence store. wfApp.InstanceStore = store// Add a StringWriter to the extensions. This captures the output // from the WriteLine activities so we can display it in the form. StringWriter sw = new StringWriter()wfApp.Extensions.Add(sw)wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e) { if (e.CompletionState == ActivityInstanceState.Faulted) { UpdateStatus(string.Format("Workflow Terminated. Exception: {0}\r\n{1}", e.TerminationException.GetType().FullName, e.TerminationException.Message))} else if (e.CompletionState == ActivityInstanceState.Canceled) { UpdateStatus("Workflow Canceled.")} else { int Turns = Convert.ToInt32(e.Outputs["Turns"])UpdateStatus(string.Format("Congratulations, you guessed the number in {0} turns.", Turns))} GameOver()}wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e) { UpdateStatus(string.Format("Workflow Aborted. Exception: {0}\r\n{1}", e.Reason.GetType().FullName, e.Reason.Message))}wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e) { UpdateStatus(string.Format("Unhandled Exception: {0}\r\n{1}", e.UnhandledException.GetType().FullName, e.UnhandledException.Message))GameOver()return UnhandledExceptionAction.Terminate}wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e) { // Send the current WriteLine outputs to the status window. var writers = e.GetInstanceExtensions<StringWriter>()foreach (var writer in writers) { UpdateStatus(writer.ToString())} return PersistableIdleAction.Unload}}启用对多个工作流类型的启动和继续执行 要继续执行工作流实例,主机必须提供工作流定义。 在此教程中有三个工作流类型,且后续教程步骤会介绍这些类型的多个版本。 WorkflowIdentity 为主机应用程序提供一种方法,此方法用于将标识信息与保留的工作流实例关联。 本节的步骤演示了如何创建实用工具类,以帮助从保留的工作流实例到对应的工作流定义映射工作流标识。 有关 有关 WorkflowIdentity 和版本管理的信息,请参见 使用WorkflowApplication 标识和版本控制。 在“解决方案资源管理器”中右击“NumberGuessWorkflowHost”并选择“添加”,“类”。 在“名称”框中键入 “WorkflowVersionMap”,然后单击“添加”。 添加以下 using 或Imports 语句和另一些using 或Imports 语句到文件的顶部。 using NumberGuessWorkflowActivitiesusing System.Activities使用以下声明替换 WorkflowVersionMap 类声明。 public static class WorkflowVersionMap { static Dictionary<WorkflowIdentity, Activity>map// Current version identities. static public WorkflowIdentity StateMachineNumberGuessIdentitystatic public WorkflowIdentity FlowchartNumberGuessIdentitystatic public WorkflowIdentity SequentialNumberGuessIdentitystatic WorkflowVersionMap() { map = new Dictionary<WorkflowIdentity, Activity>()// Add the current workflow version identities. StateMachineNumberGuessIdentity = new WorkflowIdentity { Name = "StateMachineNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }FlowchartNumberGuessIdentity = new WorkflowIdentity { Name = "FlowchartNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }SequentialNumberGuessIdentity = new WorkflowIdentity { Name = "SequentialNumberGuessWorkflow", Version = new Version(1, 0, 0, 0) }map.Add(StateMachineNumberGuessIdentity, new StateMachineNumberGuessWorkflow())map.Add(FlowchartNumberGuessIdentity, new FlowchartNumberGuessWorkflow())map.Add(SequentialNumberGuessIdentity, new SequentialNumberGuessWorkflow())} public static Activity GetWorkflowDefinition(WorkflowIdentity identity) { return map[identity]} public static string GetIdentityDescription(WorkflowIdentity identity) { return identity.ToString()} }WorkflowVersionMap 包含三个工作流标识,这些工作流标识从本教程映射到三个工作流定义,且在工作流启动和继续执行时用于以下小节。 启动新工作流 为btnNew 添加Click 处理程序。 若要添加处理程序,则切换到窗体的“设计视图”,并双击 btnNew。 系统将添加 btnNew_Click 处理程序,且视图切换到窗体的代码视图。 无论用户何时单击此按钮,均会启动新工作流。 private void btnNew_Click(object sender, EventArgs e) { // Start a new workflow. } 将下面的代码添加到单击处理程序中。 此代码可创建由工作流的输入参数组成的字典,由参数名称进行键控。 此字典有一个项,包含在范围组合框中检索的随机生成数的范围。 var inputs = new Dictionary<string, object>()inputs.Add("MaxNumber", Convert.ToInt32(cboRange.SelectedItem))接下来添加以下启动工作流的代码。 使用WorkflowVersionMap 帮助器类来检索 WorkflowIdentity 以及与选定工作流的类型对应的工作流定义。 接下来,使用工作流定义、WorkflowIdentity 和由输入参数组成的字典来创建新的 WorkflowApplication 实例。 WorkflowIdentity identity = nullswitch (cboType.SelectedItem.ToString()) { case "SequentialNumberGuessWorkflow": identity = WorkflowVersionMap.SequentialNumberGuessIdentitybreakcase "StateMachineNumberGuessWorkflow": identity = WorkflowVersionMap.StateMachineNumberGuessIdentitybreakcase "FlowchartNumberGuessWorkflow": identity = WorkflowVersionMap.FlowchartNumberGuessIdentitybreak}Activity wf = WorkflowVersionMap.GetWorkflowDefinition(identity)WorkflowApplication wfApp = new WorkflowApplication(wf, inputs, identity)接下来,添加以下代码,此代码将工作流添加到工作流列表中,并在窗体上显示工作流的版本信息。 // Add the workflow to the list and display the version information. WorkflowStarting = truecboInstanceId.SelectedIndex = cboInstanceId.Items.Add(wfApp.Id)lblVersion.Text = identity.ToString()WorkflowStarting = false调用ConfigureWorkflowApplication 为此WorkflowApplication 实例配置实例存储区、扩展和工作流生命周期处理程序。 // Configure the instance store, extensions, and // workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp)最后,调用 Run。 // Start the workflow. wfApp.Run()以下示例是完整的 btnNew_Click 处理程序。 private void btnNew_Click(object sender, EventArgs e) { // Start a new workflow. var inputs = new Dictionary<string, object>()inputs.Add("MaxNumber", Convert.ToInt32(cboRange.SelectedItem))WorkflowIdentity identity = nullswitch (cboType.SelectedItem.ToString()) { case "SequentialNumberGuessWorkflow": identity = WorkflowVersionMap.SequentialNumberGuessIdentitybreakcase "StateMachineNumberGuessWorkflow": identity = WorkflowVersionMap.StateMachineNumberGuessIdentitybreakcase "FlowchartNumberGuessWorkflow": identity = WorkflowVersionMap.FlowchartNumberGuessIdentitybreak}Activity wf = WorkflowVersionMap.GetWorkflowDefinition(identity)WorkflowApplication wfApp = new WorkflowApplication(wf, inputs, identity)// Add the workflow to the list and display the version information. WorkflowStarting = truecboInstanceId.SelectedIndex = cboInstanceId.Items.Add(wfApp.Id)lblVersion.Text = identity.ToString()WorkflowStarting = false// Configure the instance store, extensions, and // workflow lifecycle handlers. ConfigureWorkflowApplication(wfApp)// Start the workflow. wfApp.Run()}继续执行工作流 为btnGuess 添加Click 处理程序。 若要添加处理程序,则切换到窗体的“设计视图”,并双击 btnGuess。 无论用户何时单击此按钮,均会继续执行工作流。 private void btnGuess_Click(object sender, EventArgs e) { } 添加以下代码,以确保在工作流列表中选择工作流,且用户的猜测是有效的。 if (this.WorkflowInstanceId == Guid.Empty) { MessageBox.Show("Please select a workflow.")return} int guessif (!Int32.TryParse(txtGuess.Text, out guess)) { MessageBox.Show("Please enter an integer.")txtGuess.SelectAll()txtGuess.Focus()return} 接下来,检索已保留工作流实例的 WorkflowApplicationInstance。 WorkflowApplicationInstance 表示保留的工作流实例,此工作流实例还未与工作流定义关联。 WorkflowApplicationInstance 的DefinitionIdentity 包含已保留工作流实例的 WorkflowIdentity。 本教程中使用 WorkflowVersionMap 实用工具类,将 WorkflowIdentity 映射到正确的工作流定义。 对工作流定义进行检索后,即可使用正确的工作流定义创建 WorkflowApplication。 WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(this.WorkflowInstanceId, store)// Use the persisted WorkflowIdentity to retrieve the correct workflow // definition from the dictionary. Activity wf = WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity)// Associate the WorkflowApplication with the correct definition WorkflowApplication wfApp = new WorkflowApplication(wf, instance.DefinitionIdentity)创建WorkflowApplication 后,即可通过调用 ConfigureWorkflowApplication 来配置实例存储区、工作流生命周期处理程序和扩展。 这些步骤必须在每次创建新的 WorkflowApplication 时执行,且必须在将工作流实例加载到 WorkflowApplication 中之前执行。 在加载工作流后,此工作流通过用户的猜测继续执行。 // Configure the extensions and lifecycle handlers. // Do this before the instance is loaded. Once the instance is // loaded it is too late to add extensions. ConfigureWorkflowApplication(wfApp)// Load the workflow. wfApp.Load(instance)// Resume the workflow. wfApp.ResumeBookmark("EnterGuess", guess)最后,清除猜测文本框,并使窗体准备接受其他猜测。 // Clear the Guess textbox. txtGuess.Clear()txtGuess.Focus()以下示例是完整的 btnGuess_Click 处理程序。 private void btnGuess_Click(object sender, EventArgs e) { if (this.WorkflowInstanceId == Guid.Empty) { MessageBox.Show("Please select a workflow.")return} int guessif (!Int32.TryParse(txtGuess.Text, out guess)) { MessageBox.Show("Please enter an integer.")txtGuess.SelectAll()txtGuess.Focus()return} WorkflowApplicationInstance instance = WorkflowApplication.GetInstance(this.WorkflowInstanceId, store)// Use the persisted WorkflowIdentity to retrieve the correct workflow // definition from the dictionary. Activity wf = WorkflowVersionMap.GetWorkflowDefinition(instance.DefinitionIdentity)// Associate the WorkflowApplication with the correct definition WorkflowApplication wfApp = new WorkflowApplication(wf, instance.DefinitionIdentity)// Configure the extensions and lifecycle handlers. // Do this before the instance is loaded. Once the instance is // loaded it is too late欢迎分享,转载请注明来源:内存溢出
评论列表(0条)