现在的位置: 首页 > 综合 > 正文

制作自定义工作流(WWF)设计器

2012年06月23日 ⁄ 综合 ⁄ 共 8642字 ⁄ 字号 评论关闭

注:

l         这是一篇翻译,来自http://msdn2.microsoft.com/en-us/library/aa480213.aspx

l         对于一些细节我没有完全翻译

l         增加了一些我的注释,在“[]”里面

l         主要是给朋友们介绍一下这方面的情况

Vihang Dalal
Software Development Engineer Test
Microsoft Corporation

May 2006

应用于:
   Windows Workflow Foundation beta 2.2
   Microsoft Visual C# Version 2.0
   Visual Studio 2005

demo下载:Download the code sample, WorkflowDesignerControl.exe.

 

 

摘要:如果你在vs2005里面安装了Visual Studio 2005 extensions for Windows Workflow Foundation,你就可以使用WWF的可视化编辑器了。这篇文章就是介绍如何在自己的程序中使用这个设计器的一些方法。并且附带有一个简单的例子程序[注:确实可以使用,默认顺序工作流,可以在程序中修改实现。]

 

主要内容包括

l         自定义设计器的介绍

l         自定义设计器的类

l         主要功能和自定义的服务(Services)

l         结论

l         更多资源

 

自定义设计器的介绍:

这篇文章主要讲述了如何使用设计器的api,以及其他扩展。

我们为什么会用到自定义设计器?

l         自定义自己的视图,可以增加/减少一些实现

l         在现有的程序中加入自己的设计器

l         [我用的Web Developer 2005 Express,所以我无法安装WWF设计器,只能用这个了]

什么时候用到这个设计器?

l         设计时:可以创建、编辑工作流

l         运行时:可以跟踪工作流状态

这里提供的例子程序可以独立于vs2005开发工具之外单独运行

 

自定义设计器的类

主要包括:DesignSurface, WorkflowView, and WorkflowDesignerLoader

DesignSurface使用WorkflowDesignerLoader来创建活动(Activety)树和其他组建的树;WorkflowView则用来显示工作流实例(一个xml文件)的默认视图.

 

DesignSurface提供一个环境(self-contained)来显示设计器组件

WorkflowDesignerLoader可以用来加载(PerformLoad())和卸载(PerformFlush())一个工作流的定义。开发者可以使用者个类来自定义工作流保存的方式,可以序列化到自己的媒介中(数据库

WorkflowView是用来显示一个具体的工作流实例的。他借助DesignSurface来显示其中activety的信息。同时他也提供很多用于显示时的控制事件(OnLayout() and OnPaint()),还提供诸如SaveWorkflowAsImage()之类的函数。

 

下边这段代码可以用来制作一个简单的winform的设计器

创建自定义WorkflowDesignerLoader:(重写PerformLoad() and PerformFlush()

·                           internal sealed class WorkflowLoader : WorkflowDesignerLoader
·                           
{
·                              
protected override void PerformLoad(IDesignerSerializationManager serializationManager)
·                                 
{
·                                    
base.PerformLoad(serializationManager);
·                                    
// Implement the logic to read from the serialized state,
·                                    // create the activity tree and the corresponding designer
·                                    // tree and add it to the designer host
·                                 }

·                            
·                              
protected override void PerformFlush(IDesignerSerializationManager manager)
·                                 
{
·                                    
// Implement the logic to save the activity tree to a
·                                    // serialized state along with any code beside elements 
·                                 }

·                           }

加载工作流,显示

·                           // Create new Design surface and loader (created as shown above)
·                            
·                           DesignSurface designSurface 
= new DesignSurface();
·                           WorkflowLoader loader 
= new WorkflowLoader();
·                            
·                           
// load the design surface using the loader. This will call the
·                           // PerformLoad method on the loader, create the activity tree and
·                           // add the corresponding designer components to the designer host
·                            
·                           designSurface.BeginLoad(loader);
·                            
·                           
// Get the designer host and retrieve the corresponding root component
·                           IDesignerHost designerHost = designSurface.GetService(typeof(IDesignerHost)) as IDesignerHost;
·                           
if (designerHost != null && designerHost.RootComponent != null)
·                           
{
·                              
// Get the designer associated with the root component
·                              IRootDesigner rootDesigner =    designerHost.GetDesigner(designerHost.RootComponent) as IRootDesigner;
·                              
if (rootDesigner != null)
·                              
{
·                                 
this.designSurface = designSurface;
·                                 
this.loader = loader;
·                              
·                                    
// Assign the default view of the rootdesigner to WorkflowView
·                                    this.workflowView = rootDesigner.GetView(ViewTechnology.Default) as          WorkflowView;
·                            
·                                    
// Add the workflow view control to winforms app
·                                    this.workflowViewSplitter.Panel1.Controls.Add(this.workflowView);
·                                    
this.workflowView.Focus();
·                                    
this.propertyGrid.Site = designerHost.RootComponent.Site;
·                              }

·                            }

 

还需要一个DesignerHost类,用来装载各种服务,和向外提供各类服务接口。

http://msdn2.microsoft.com/en-us/library/Aa480213.wfdsgnrehst02(en-us,MSDN.10).gif

 

主要功能和自定义的服务(Services)

System.Workflow.ComponentModel提供了一些默认类的实现,比方说“IIdentifierCreationService, IReferenceService, IworkflowCompilerOptionsService”等。但是如果要自定义设计器,可能需要你客户化自己的实现类(Service

1:上下文菜单和通用设计器的功能(Context Menu And Common Designer Features:);

   菜单WorkflowMenuCommandService继承自MenuCommandService,用来显示菜单命令。这些代码用来增加一些额外的命令菜单

·               // Create a new context menu
·               ContextMenu contextMenu = new ContextMenu();
·               Dictionary
<CommandID, string> selectionCommands = new Dictionary<CommandID, string>();
·                
·               
// Add the required commands
·               selectionCommands.Add(WorkflowMenuCommands.Cut, "Cut");
·               selectionCommands.Add(WorkflowMenuCommands.Copy, 
"Copy");
·               selectionCommands.Add(WorkflowMenuCommands.Paste, 
"Paste");
·               selectionCommands.Add(WorkflowMenuCommands.Delete, 
"Delete");
·               
foreach (CommandID id in selectionCommands.Keys)
·               
{
·                     MenuCommand command 
= FindCommand(id);
·                     
if (command != null)
·                      
{
·                        
// For each command create a new menu item and add an
·                        MenuItem menuItem = new MenuItem(selectionCommands[id], new          EventHandler(OnMenuClicked));
·                        menuItem.Tag 
= command;
·                        contextMenu.MenuItems.Add(menuItem);
·                     }

·               }

·                
·               
// Handle the event when the MenuItem is clicked
·               private void OnMenuClicked(object sender, EventArgs e)
·               
{
·                
// Retrieve the menu item that was clicked
·                MenuItem menuItem = sender as MenuItem;
·                
if (menuItem != null && menuItem.Tag is MenuCommand)
·                     
{
·                        
// invoke the command corresponding to the menu item clicked
·                        MenuCommand command = menuItem.Tag as MenuCommand;
·                        command.Invoke();
·                     }

·               }

这样,在界面上就可以显示出你自己的上下文菜单了

关于菜单命令的响应处理:

·               // Invoke the standard command with the command id of the command clicked
·               this.workflowDesignerControl1.InvokeStandardCommand(WorkflowMenuCommands.Expand);
·                
·               
public void InvokeStandardCommand(CommandID cmd)
·                  
{
·                     IMenuCommandService menuService 
=
·                     GetService(
typeof(IMenuCommandService)) as IMenuCommandService;
·                     
if (menuService != null)
·                     menuService.GlobalInvoke(cmd);
·                  }

http://msdn2.microsoft.com/en-us/library/Aa480213.wfdsgnrehst03(en-us,MSDN.10).gif


2
:生成后台代码MemberCreationService,和EventBindingService

   MemberCreationService可以用来生成关于Member,Filed的之类的定义

   EventBindingService则可以生成和设计界面上事件关联的代码的映射。比方说“CodeActivty”要执行的代码xxx_Excute函数和后台编译后的代码的关联。

·               // create code member method

·               CodeMemberMethod method 
= new CodeMemberMethod();

·               method.Name 
= methodName;

·               method.Parameters.AddRange(paramCollection);

·               method.ReturnType 
= new CodeTypeReference(returnType);

·               method.Attributes 
= modifiers;

·                

·               
//push the method into the code compile unit

·               typeDeclaration.Members.Insert(index, method);

·                

·               
// refresh the code compile unit

·               TypeProvider typeProvider 
= (TypeProvider)this.serviceProvider.GetService(typeof(ITypeProvider));

·               typeProvider.RefreshCodeCompileUnit(
this.ccu,new EventHandler(RefreshCCU));

 其后台代码可能这样

·               public partial class Workflow1 : SequentialWorkflowActivity
·               
{
·                       
private void EventHandler(object sender, System.EventArgs e)
·                       
{
·              

【上篇】
【下篇】

抱歉!评论已关闭.