资源描述
编号:时间:2021年x月x日书山有路勤为径,学海无涯苦作舟页码:第94页 共94页【开源项目】Silverlight工作流设计器Silverlight工作流设计器是一款开源项目,支持用户在线设计工作流程,或者项目流程,支持在线拖拽,以 及鼠标右键支持。 具体来说,这样的流程设计器应该具有以下的特点: 图形化的方式显示 流程 支持拖拽创建和修改流程 导出图形对应的xml描述文件 根据流程xml描述文件Silverlight工作流设计器是一款开源项目,支持用户在线设计工作流程,或者项目流程,支持在线拖拽,以及鼠标右键支持。具体来说,这样的流程设计器应该具有以下的特点: 图形化的方式显示流程 支持拖拽创建和修改流程 导出图形对应的xml描述文件 根据流程xml描述文件显示流程图点击访问本系列专题文章源代码下载数据库下载Silverlight构建图形化工作流程设计器(一)前言 Silverlight发布已经很久了,具体是什么就不多说,大家一定很清楚。最关心的就是其中的跨浏览器能力,以及强大的用户界面表现能力。于是决定使 用它来实现一个流程设计工具,以替代以前的流程设计器(原来是用vml实现,只能在IE浏览器上工作),因为第一次接触silverlight,在学习、 工作的过程中肯定会遇到很多的问题前言Silverlight发布已经很久了,具体是什么就不多说,大家一定很清楚。最关心的就是其中的跨浏览器能力,以及强大的用户界面表现能力。于是 决定使用它来实现一个流程设计工具,以替代以前的流程设计器(原来是用vml实现,只能在IE浏览器上工作),因为第一次接触silverlight,在 学习、工作的过程中肯定会遇到很多的问题,将这个学习新知识、解决问题的过程记录下来,肯定能找到许多志同道合的朋友,也请大家抱着这种态度阅读本文。本文主要讲述使用2008开发一个基于silverlight的流程设计器。在进入正文之前,先说一下开发环境的配置。使用2008作为开发工具,需要下载一个Silverlight tools for virsual studio 2008 sp1,地址在 silverlight应用了。本系列文章包含以下几部分(可能有变)。系统范围系统设计类设计Xml设计美化重构一、系统范围在开始之前,先来看一下系统将要完成什么样的功能。具体来说,这样的流程设计器应该具有以下的特点:图形化的方式显示流程支持拖拽创建和修改流程导出图形对应的xml描述文件根据流程xml描述文件显示流程图注意:本文只将焦点放置在图形的描述上,不涉及流程的各种属性,不过您完全可以在此基础上创建一个包含流程属性设置的应用程序。另外,本文是随着程序的编写进度而撰写的,程序在不断的完善,本文也将不断的修改完善。在这个过程中将随时提供可以运行的程序供下载。下面的图形具体的显示了系统将要完成的功能:二、系统设计 从上面的图形来看,我们的系统将包含三个大的对象: 活动(activity):如上图中的 方框图(三角图,圆形图) 对应的对象,这个对象代表工作流中的一个活动。 规则(rule):如上图中的带箭头的直线, 二、系统设计从上面的图形来看,我们的系统将包含三个大的对象:活动(activity):如上图中的 方框图(三角图,圆形图) 对应的对象,这个对象代表工作流中的一个活动。规则(rule):如上图中的带箭头的直线,这个对象代表了工作流中的规则。设计面板:设计面板是流程图的容器对象。系统对象确定以后,再来看一下系统功能描述:新增活动:创建一个活动的实例,并将这个实例添加到设计面板中。新增规则:创建一个规则的实例,并将这个实例添加到设计面板中。拖拽规则实例:规则实例可以被鼠标拖拽,规则实例表现为一个带箭头的直线,可以拖拽直线的开头部分,也可以拖拽直线的结尾部分,或者拖拽直线中间的 部分。拖拽开头部分时,直线的开头部分随鼠标变化位置,但结尾部分位置不改变。拖拽结尾部分时,直线的开头部分随鼠标变化位置,但结束部分位置不改变。拖 拽中间部分,整条直线随鼠标改变位置。在拖拽开头或者结尾部分,并在某一个活动实例上放开鼠标左键,那么将建立活动和规则的关联关系。拖拽活动实例:活动实例可以被鼠标拖拽,如果这个活动有相关联的规则,那么规则位置也随鼠标变化。支持活动和规则的删除:支持删除活动实例和规则实例,删除活动实例时,同时删除关联的规则实例。根据图形导出xml文件:导入xml文件生成图形:通过上面的分析,对流程设计器有一个大概的了解,在进入具体的类设计之前还是有几点需要提醒的:silverlight和的运行模型的不同和编制程序时的注意点。Silverlight和都可以使用c#进行编程设计,但他们的运行方式却截然不同。A中的#代码是需要您的服 务器执行的(IIS)后,将执行后的html代码发送到客户端的浏览器,而silverlight中的c#代码却是在客户端的浏览器中运行的。对于页面,您的每一次请求都将实例化一个Page类的对象,你在服务器代码中的C#代码的各种变量都将被重新初始化。但是 silverlight不需要发送代码到服务器,而是在本地浏览器中完成了您编写的#代码,这种方式更类似于传统的VB或者VC编写的c/s架构的程 序。正是基于以上的理解,我们把silverlight看作是c/s架构的编程方式,所以可以进行上面的各种类的设计。这样使用c/s编程方式编写一个 流程设计器,通过silverlight技术,最终可以通过浏览器来给客户使用。对客户而言,这是一个b/s架构的程序,而对于程序员来说,其实是c/s 架构的。下面将进入具体的类的设计,并提供一个可运行的程序。Silverlight构建图形化工作流程设计器(二)三、类的设计 在进行类设计之前,先说一下silverlight中使用怎么表示上面描述的类。在silverlight可以使用 用户控件( silverlight user contro)来描述各种具有用户界面的类,如上文所讲的活动类,规则类。操作很简单,在 2008中增加一个新的 silverlight user c三、类的设计在进行类设计之前,先说一下silverlight中使用怎么表示上面描述的类。在silverlight可以使用 用户控件( silverlight user contro)来描述各种具有用户界面的类,如上文所讲的活动类,规则类。操作很简单,在 2008中增加一个新的 silverlight user contro就可以了。其实是一个xaml文件。在xaml文件中布局用户界面,在对应的xam.cs文件中编写后台方法即可。需要说一下的是,在进行鼠标拖动活动或者规则移动时,规则和活动的动态定位使用的是相对于容器来的相对位置,也就是使用Canvas.Top和Canvas.Left属性进行定位。还有一点需要说明的就是,对于活动和规则的关联有几点需要注意。一个规则可以关联到两个不同的活动,一个为起始活动(起始端点关联)。一个为终结活动(终结端点关联)规则的起始活动和终结活动不能为同一个活动。任何两个规则,他们的起始活动和终结活动不能相同,也就是说在不同的两个活动之间,不能有重复的规则关联。3.1 活动类的设计(Activity)活动代表工作流中的一个活动节点,在流程图上表现为一个方框图,可以被拖拽,可以关联到一个规则的开始或者结束。3.1.1 Xam下面的代码表示了活动类的外观从上面代码可以看出,活动类主要包含一个矩形的图形,还有一个删除按钮。图形显示如下:3.12 后台代码活动类主要实现主要动作(函数)鼠标拖拽删除关联到规则(增加,删除)输出活动xml描述导入xml描述还有一些主要属性:活动标示(ID)活动名称(Name)所有关联的规则的集合以及一些主要的事件:移动删除具体代码不再贴出,大家可以下载源代码运行。一个规则从图形上被分成三个部分,起始端点(白色),中间线段,终结端点(黑色)(在实际环境中,应该整体表现为一个带箭头的线段,为了便于描述, 先这样表示,在后面的美化部分将作修改)。这三个部分都可以被鼠标拖动,当拖动起始端点时,起始端点随着鼠标变化而变化位置,终结端点不动,中间线段根据 起始端点和终结端点计算位置。拖动终结端点类似于拖动起始端点。当拖动中间线段时,整个规则图形(包括起始端点,中间线段,终结端点)随着鼠标移动而移 动。另外一个需要仔细考虑的是,当拖动规则,并且将端点移动到活动上时,进行规则和活动关联的时机。有以下几个时机可以考虑:拖动规则进入活动范围。(活动的MouseEnter事件)拖动规则结束后,放开鼠标。对于第一种情况,当拖动规则并且进入互动范围时,无法触发活动的MouseEnter事件。暂时无法解决。(但是在放开鼠标,并且在活动上移动时, 此时触发MouseEnter事件。但是这样做会存在某些特定的bug)。因此使用第二种方法进行关联,也就是在规则的 MouseLeftButtonUp事件中遍历当前所有的活动,检查规则是否处于活动的范围内,如果在,那么就进行关联。3.2.1 xaml下面的代码描述了规则类的xaml1 781516232428 293233343536373.2.2 后台代码规则类主要实现主要动作(函数)鼠标拖拽删除关联到活动(增加,删除)输出规则xml描述导入xml描述还有一些主要属性:规则标示(ID)规则名称(Name)起始活动结束活动以及一些主要的事件:移动删除3.3 容器类的设计容器类主要功能就是用来提供一个设计面板,可以增加,删除工作流元素(活动,规则),导入xml和导出xm。3.3.1 xam下面的容器的xaml代码14 5 678910 1112131415 161718192021222324 252627282930313233343536下图是容器的外观3.3.2 后台代码规则类主要实现主要动作(函数)增加活动删除活动增加规则删除规则导入xm导出xm还有一些主要属性:活动集合规则集合流程标示(ID)流程名称(Name)好了,其实也没有说什么,大家还是看代码吧,因为比较仓促,有些写得比较乱,有些也没有注释,以后会慢慢完善,既然是第一个版本,就叫做workflowDesigner.S0.1版吧。下面的章节进入导出xml及根据xml文件生成流程图,并且会讨论一些更有意思的话题. 源代码下载Silverlight构建图形化工作流程设计器(三)新功能调查:系统到这里已经具备一个设计器的雏形了,当然还有很多需要完善的功能,如果您在这方面有经验,请提出 您的宝贵意见,也可以留下您想要实现的功能,在后续版本中,我们将考虑您的意见,非常感谢:) 本文继续前文的内容,主要讲述与导入xm,导出xm,xml存储有新功能调查:系统到这里已经具备一个设计器的雏形了,当然还有很多需要完善的功能,如果您在这方面有经验,请提出您的宝贵意见,也可以留下您想要实现的功能,在后续版本中,我们将考虑您的意见,非常感谢:)本文继续前文的内容,主要讲述与导入xm,导出xm,xml存储有关的一些内容。包含以下部分:设计一个流程图的xml描述文件将流程图导出为xm根据xml文件呈现流程图在完成以上内容后,进一步深入思考,既然可以将流程的当前状态保存为xm,那么在每次流程改变的时候将当前状态保存到内存中,在需要的时候再从内存中还原,就可以实现word里面的 撤销 与 前进 的功能了,所以功能就加多了两个。撤销前进在进一步,如果将内存保存的xml对象集合按照一定的频率自动播放,是不是就是一个动画了,呵呵,我们可以用这个来做一个简单的动画片了。四、xml存取4.1 xml内容就是将流程图保存为xml文件,以及根据xml文件还原流程图的功能。首先来看一下xml文件的格式。Xml文件用来描述流程的,在本文中,流程的布局信息主要有几个方面:流程的属性信息。例如流程名称等活动和规则的属性信息,例如活动名称等活动和规则的位置信息活动和规则的关联信息我们设计出一个可以完全描述上面内容的xml文件即可,下面给出这个xml描述的一个实现。 上面的内容不用多讲了,大家看名字应该可以猜的出来。我们还可以使用xsd.exe工具(.netframework sdk里面带有)生成对应的workflow.xsd文件,在根据.xsd文件生成Class,这个class就是操作这个xml文件的,.net真是太 方便了。(这里就先不这么做了,而直接使用LINQ To Xml来操作上面的xml文件)如果您不了解xml相关的一些技术,可以参考4.2 导入、导出有几个生成xml的方法。一个是将流程对象序列化,使用对象序列化的方法。另一个是让对象自己生成xml片段,这里采用第二种方法。首先为了导入导出xm,容器、活动、规则、类需要增加两个方法。ToXmlString()LoadFromXmlString(string xmlNode)第一个用于生成表达本对象的xml片段,第二个用户根据xml片段来生成相应的对象。使用这两个方法就可以将流程当前状态转化为xml存储了。具体 实现大家看源代码即可。未找到在silverlight中动态生成一个文件下载,和从用户本地的系统中提取文件的方法,生成xml的文件存放在一个 TextBox中,拷贝就可以。4.3 撤销及前进有了上面的生成xml及载入xml的基础,就可以设计出一个支持撤销和前进功能的应用了。有c/s编程经验的朋友对此一定不陌生,搞b/s开发的可能不太熟悉,这里简单实现,并说明一下思路。在内存中定一个两个堆栈(Stack),一个保存用于撤销的xml集合,一个保存用于前进的xml集合。当出现下面的情况是,将流程当前状态的xml描述进入出栈和入栈的动作。用户进行流程修改的时候,将修改后的xml描述压入(Push) 撤销堆栈,并清空 前进堆栈。当用户点击 撤销 按钮时,从撤销堆栈 弹出(pop)一个xm,使用这个xml来还原流程图,同时将这个xml压入 前进堆栈。当用户点击 前进 按钮时,从前进堆栈 弹出(pop)一个xm,使用这个xml来还原流程图,同时将这个xml压入 撤销堆栈。也就是说两个堆栈协同工作,就可以完成撤销、前进的功能了。另外撤销前进功能的xml存储也可以有两种方式,一种是增量存储,也就是只存储改变的部分,另一种的完全存储,也就是存储当前整个流程图的xm。对于第一种比较麻烦,对于第二种方式,系统中的函数已经支持,所以采用第二种方式,就是比第一种方式存储的xml长度大了一点。本章的内容就结束了,请留下您的宝贵意见!后文再续!源代码下载Silverlight构建图形化工作流程设计器(四)按计划程序到这里就差不多结束了,但是有很多朋友希望能继续完善这个程序,并增加有关工作流属性的内容,应各位朋友要求,把这个系列继续下去,并增加流程属性的一些内容。工作流在现代企业中广泛应用,本文不强求完成一个大而全的流程应用,而是做一个框架类的东西,方按 计划程序到这里就差不多结束了,但是有很多朋友希望能继续完善这个程序,并增加有关工作流属性的内容,应各位朋友要求,把这个系列继续下去,并增加流程属 性的一些内容。工作流在现代企业中广泛应用,本文不强求完成一个大而全的流程应用,而是做一个框架类的东西,方便进行二次开发和扩展。大家从前面的内容可以看出,本文很少直接贴代码上来,而是主要侧重于创作一个应用程序过程中的遇到的问题以及解决问题的思路和方法(当然也包括使用 silverlight遇到的问题)。并且说明解决一个问题的多个方法之间的取舍原因。当然这个原因不是绝对的,根据时间的推移和思路的延伸,我们还可以 找到更加合适的解决问题的方法。在这个学习silverlight的过程中,希望和大家分享一下学习的心得,关于silverlight的,关于系统设计都有,只要使我觉得比较新鲜有趣的。也希望各位大虾,新手多多指点。五 美化需要美化的内容有很多,目前想到并且打算做的部分有以下几方面的内容:规则使用带箭头的直线活动根据不同的活动类型显示不同的形状。界面调整5.1 规则使用带箭头的直线在silverlight中的 Line类没有找设置箭头的属性,所以我们要自己做一个箭头放在规则的尾部,能想到的有两种方法:使用一个箭头的图片放在规则的尾部。自己编写一个表示箭头的类,并将这个类放在规则的尾部。对于这两种方法,都涉及到一个问题,就是根据规则在不同的位置,箭头的方向要随着规则的变化角度做一个改变,以适应规则的角度。第一种方法比较简单,但是使用图片一个是增加客户端下载内容的大小,还有不方便改变显示的颜色,每次改变颜色都要换新的图片,不方便。那么我们就自己写一个表示图片的类,方式在规则的尾部。这个类继承自System.Windows.Controls.Canvas,我们叫它 Arrowhead ,Arrowhead类包含两个子控件,分别是两个 Line(直线)类,这两个直线类按照不同的角度排列,就可以形成一个箭头,类似下面的图形:把这个类放在规则类的尾部,就形成了一个带箭头的直线,如下所示:这样用几个对象合成了一个带箭头的直线。接下来的问题就是当直线被拖转进行位移和旋转的时候,箭头也要随着进行相同的位移和旋转。虽然我们不知道如何具体的实现,但是经过分析得知,这 个旋转的角度和直线的起始点坐标位置和终点坐标位置有关,那么我们给箭头类增加一个方法来设置这个变化,这个方法有两个参数分别表示直线的起始和终结位置 坐标,这样一个带箭头的直线就完成了。这样的过程可用下图来表示:接下来我们在规则类的xaml文件中这册这个类,类似下面的代码:其中最后一行xmlns:Shareidea=clr-namespace:Shareidea.Web.UI.Contro.Workflow.Designer我们在当前xaml中注册了命名空间Shareidea.Web.UI.Contro.Workflow.Designer那么在当前xaml文件中既可以使用类似于这样的声明来使用自定义类了。下面的代面具体表示了这样的一个箭头类,其中用到了数学公式的类,System.Math.Sin(double d),这样的一个类用来计算一个角度的Sin值,需要注意的是,我们平常讲的30度的Sin不能直接作为参数传递,因为这个函数的参数是一个弧度值,而不 是一个角度的值,需要做一个转换,例如 Math.PI * 30/ 180.0 ,经过这样一个转换,把角度30转换成一个弧度值就可以了。publicclassArrowhead:System.Windows.Controls.CanvasintarrowLenght=12;intarrowAngle=30;/箭头的长度/publicintArrowLenghtgetreturnarrowLenght;setarrowLenght=value;/箭头的与直线的夹角/publicintArrowAnglegetreturnarrowAngle;setarrowAngle=value;LinelineLeft;LinelineRight;publicintZIndexgetreturn(int)this.GetValue(Canvas.ZIndexProperty);setthis.SetValue(Canvas.ZIndexProperty,value);publicvoidSetAnge(PointbeginPoint,PointendPoint)publicBrushStrokegetreturnlineRight.Stroke;setlineRight.Stroke=value;lineLeft.Stroke=value;publicdoubleStrokeThicknesssetlineRight.StrokeThickness=value;lineLeft.StrokeThickness=value;getreturnlineLeft.StrokeThickness;voidSetAngleByDegree(doubledegreeLeft,doubledegreeRight)doubleangleSi=Math.PI*degreeLeft/180.0;doublex=System.Math.Sin(Math.PI*degreeLeft/180.0);doubley=System.Math.Sin(Math.PI*(90-degreeLeft)/180.0);lineLeft.X2=-ArrowLenght*x;lineLeft.Y2=-ArrowLenght*y;x=System.Math.Sin(Math.PI*degreeRight/180.0);y=System.Math.Sin(Math.PI*(90-degreeRight)/180.0);lineRight.X2=ArrowLenght*x;lineRight.Y2=-ArrowLenght*y;/根据直线的起始点和结束点的坐标设置箭头的旋转角度/publicvoidSetAngleByPoint(PointbeginPoint,PointendPoint)doublex=endPoint.X-beginPoint.X;doubley=endPoint.Y-beginPoint.Y;doubleangle=System.Math.Atan(x/y)*180/Math.PI;if(endPoint.YbeginPoint.Y)SetAngleByDegree(ArrowAngle+angle)-180,(ArrowAngle-angle)-180);elseSetAngleByDegree(ArrowAngle+angle,ArrowAngle-angle);publicArrowhead()lineLeft=newLine();lineRight=newLine();this.Children.Add(lineLeft);this.Children.Add(lineRight);lineLeft.X1=0;lineLeft.Y1=0;lineRight.X1=0;lineRight.Y1=0;SetAngleByPoint(newPoint(0,0),newPoint(15,15);Silverlight构建图形化工作流程设计器(五)本文主要侧重于创作一个应用程序过程中的遇到的问题以及解决问题的思路和方法(当然也包括使用 silverlight遇到的问题)。并且说明解决一个问题的多个方法之间的取舍原因。当然这个原因不是绝对的,根据时间的推移和思路的延伸,我们还可以 找到更加合适的解决问题的方法本文主要侧重于创作一个应用程序过 程中的遇到的问题以及解决问题的思路和方法(当然也包括使用silverlight遇到的问题)。并且说明解决一个问题的多个方法之间的取舍原因。当然这 个原因不是绝对的,根据时间的推移和思路的延伸,我们还可以找到更加合适的解决问题的方法。在这个学习silverlight的过程中,希望和大家分享一下学习的心得,关于silverlight的,关于系统设计都有,只要使我觉得比较新鲜有趣的。也希望各位大虾,新手多多指点。五 美化5.2活动根据不同的活动类型显示不同的形状要是活动根据不同的类型显示不同的形状,我们也有几种方法:根据类型不同,定义不同的图形显示根据类型不同,对现有的活动图形进行剪裁处理。第一种方法会给我们已有的类造成比较大的修改,因为涉及到图形在移动时候需要对关联的规则类进行动态定位的问题。使用第二种方法去没有这个问题,只需要动体的对活动类进行剪裁处理就可以了。活动类型有以下几种:常规交互活动,也就是需要人工参与的活动。自动活动,没有人工参与的活动,后台自动完成。分支活动,包括与分支、或分支汇聚活动,包括与汇聚,或汇聚,投票汇聚。起始与终结活动当我们给活动指定不同的类型时,希望显示不同的活动形状。对于常规交互活动,显示矩形图形,对于分支和汇聚活动显示菱形,对于其他活动,显示圆形。矩形和圆形分别用EllipseGeometry和RectangleGeometry类进行裁减就可以了,对于菱形,需要使用PathGeometry类进行裁减,这个类的使用有点复杂,需要定义多个转折点。然后这些点围成一个菱形。5.3 给活动和规则增加配置界面为了给活动设置类型,我们需要给活动增加一个配置界面,具体还是增加一个用户控件 ,xaml代码如下:上面的代码有两点需要介绍的:ComboBox控件。Silverlight2.0中没有dropdownlist控件,但是有一个更加强大和灵活的ComboBox控件。 ComboBox可以使用内容模板的方式添加子元素(Item),我们可以使用任意一个silverlight控件作为ComboBox的子元素,这样就 给我们很大的灵活性,用来构造复杂的下拉框内容了。控件的绑定语法。在上面的xaml代码中,使用到了类似于TextBlock Text=Binding Path=Name 这样的代码,这个是silverlight的绑定语法。在后台代码中, 使用下面的代码进行绑定public ActivitySetting()InitializeComponent();List Cus = new List();Cus.Add(new ActivityTypeItem(AND_BRANCH, 与分支活动);Cus.Add(new ActivityTypeItem(AND_MERGE, 与汇聚活动);Cus.Add(new ActivityTypeItem(AUTOMATION, 常规自动活动);Cus.Add(new ActivityTypeItem(COMPLETION, 终结活动);Cus.Add(new ActivityTypeItem(DUMMY, 哑活动);Cus.Add(new ActivityTypeItem(INITIA, 初始化活动);Cus.Add(new ActivityTypeItem(INTERACTION, 常规交互活动);Cus.Add(new ActivityTypeItem(OR_BRANCH, 或分支);Cus.Add(new ActivityTypeItem(OR_MERGE, 或汇聚活动);Cus.Add(new ActivityTypeItem(SUBPROCESS, 子流程);Cus.Add(new ActivityTypeItem(VOTE_MERGE, 投票汇聚活动);cbActivityType.ItemsSource
展开阅读全文