VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 编程开发 > Objective-C编程 >
  • WF编程系列之自定义活动继承法和活动组件

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  从根本上来说,采用组成法或继承法来创建自定义活动并没有太大的差别.之前我们创建的GetUploadActivity就是从SequenceActivity类继承的.组成法和继承法都使用了继承.

  继承法相对组成法来说更容易理解.在组成法中,我们关注于如何组织自定义活动内的子活动,并且创建了活动属性和执行模型.而继承法是一种相对更加初级的方法.让我们用继承法编写一个向控制台输出字符串的自定义活动吧.

  5.5.1 CONSOLEWRITEACTIVITY创建这个活动的第一步,我们编写一个简单的类.不需要XAML,也不需要设计器,仅仅使用下面的C#代码:

usingSystem;
usingSystem.Workflow.ComponentModel;
usingSystem.ComponentModel;
usingSystem.Workflow.ComponentModel.Design;
publicclassConsoleWriteActivity:Activity
{
publicstringText
{
get{return_text;}
set{_text=value;}
}
privatestring_text;
protectedoverrideActivityExecutionStatusExecute(ActivityExecutionContextexecutionContext)
{
Console.WriteLine(Text);
returnActivityExecutionStatus.Closed;
}
}

  这个类从System.Workflow.ComponentModel.Activity类继承而来.我们知道,Activity是WF中所有活动的基类.我们的活动有一个简单的属性Text,而且并没有被升级为依赖属性,也就是说它不可以进行数据绑定.但我们仍然可以在工作流设计器中设置这个属性的值为字符串.

  这个类最重要的功能是Execute方法.通过重写Execute方法,我们就可以完全控制对活动的行为.当活动运行时,Runtime会调用我们编写的Execute方法,然后将Text属性输出到控制台.然后我们返回一个结果为Closed的执行状态以通知Runtime活动完成了执行过程.

 
 

  这时,我们可以编译自定义活动,接下来创建一个新的工作流.打开工作流设计器,就可以在工具箱中(当然,我们需要引用包含这个活动的程序集)看到这个活动.如果我们将其拖拽到设计器中,就会发现这个活动看起来和基本类库的其它活动差不多.

《WF编程》系列之39 - 自定义活动:继承法与活动组件

  注意活动的Text属性也显示在了属性面板中(Misc分类下).我们可以通过System.ComponentModel和System.Workflow.ComponentModel命名空间中的特性来控制这个属性的设计时功能.举例来说,添加下面的代码到Text属性可以提供一个默认值,描述和属性的分类.

[DefaultValue("")]
[Description("Thetexttowritetotheconsole")]
[Category("Activity")]
publicstringText
{
get{return_text;}
set{_text=value;}
}

  特性并不是只能附加在属性上,我们还可以用特性来控制活动的行为和外观.

  5.5.2 活动组件我们可以关联活动组件(activity component)到我们的自定义活动,籍此来调整它的行为.两个重要的组件类型是活动设计器和活动验证器.我们使用特性来将组件和活动进行关联.而且很明显可以知道这些组件是可选的,因为前边的自定义活动范例就不需要使用任何组件.但是,许多优秀的自定义活动都或通过使用这些组件来增强设计器体验.

  在前面创建的自定义活动中,如果工作流设计者永远都不给Text属性分配值得话会发生什么状况呢?我们的ConsoleWrite活动在缺少有效的Text属性的情况下是不可用的,所以我们必须事先就假定编写者会犯这个错误.如果我们为自定义活动关联了验证器,那我们就可以给编写者一个恰当的反馈.

 
 

  5.5.2.1 活动验证器活动验证器在工作流设计和编译之间执行,它的作用是确保活动的配置在运行时都正确.想要执行验证,我们需要编写一个新的验证器类,让它继承ActivityValidator类,并重写父类的Validate方法.下面的Validate方法将确保我们的自定义控件中没有空的Text属性:

publicoverrideValidationErrorCollectionValidate(ValidationManagermanager,objectobj)
{
ValidationErrorCollectionerrors=base.Validate(manager,obj);
ConsoleWriteActivityactivity=objasConsoleWriteActivity;
if(activity.Parent!=null&&String.IsNullOrEmpty(activity.Text))
{
errors.Add(
ValidationError.GetNotSetValidationError("Text"));
}
returnerrors;
}

  我将所有的验证错误都添加到一个ValidationErrorCollection集合并且返回.需要注意的是,在这段代码中我们还检查了这个活动是否有父活动.这是因为Validate方法在我们编译自定义活动自身时也会执行,那么如果这时活动包含一个空的Text属性,编译时就会得到一个”属性Text的值没有设置”的错误.而如果活动有父活动存在,就可以认为活动在工作流内部,这时它才是需要验证的.

  接着,我们通过使用ActivityValidator特性将验证器附加到自定义活动上.

[ActivityValidator(typeof(ConsoleWriteValidator))]
publicclassConsoleWriteActivity:Activity
{
//…
}

  活动验证器并不对属性检查做任何限制,也就是说,我们可以检查任何事情.例如,我们可以决定自定义活动是否只能作为While活动的子活动.我们可以检查父活动的类型,如果发现类型不是While活动的话就抛出验证错误.

 
 

  5.5.2.2 活动设计器活动设计器用来控制活动在设计时的外观和行为.我们需要编写一个新的设计器类,使它从ActivityDesigner类继承并重载父类的虚拟方法.通过重载OnPaint方法,我们可以在设计器中画出自己的活动形状.我们还可以像Windows UI开发人员那样重载诸如OnMouseDown,OnDragOver等许多方法.下列代码为我们的自定义活动实现了设计时外观:

publicclassConsoleWriteDesigner:ActivityDesigner
{
ConsoleWriteActivity_activity;
protectedoverridevoidInitialize(Activityactivity)
{
_activity=activityasConsoleWriteActivity;
base.Initialize(activity);
}
protectedoverrideSizeOnLayoutSize(ActivityDesignerLayoutEventArgse)
{
returnnewSize(120,70);
}
protectedoverridevoidOnPaint(ActivityDesignerPaintEventArgse)
{
e.Graphics.FillRectangle(Brushes.Black,
Location.X,
Location.Y,
Size.Width,
Size.Height);
StringFormatformat=newStringFormat();
format.Alignment=StringAlignment.Center;
Rectanglerect=newRectangle(Location.X,
Location.Y,
Size.Width,
15);
e.Graphics.DrawString(Activity.QualifiedName,
DesignerTheme.Font,
Brushes.Yellow,
rect,
format);
using(Fontfont=newFont("LucidaConsole",7))
{
e.Graphics.DrawString(">"+_activity.Text,
font,
Brushes.White,
rect.X,
rect.Y+20);
}
}
}

  我们可以在Initialize方法中获取自定义活动自身的引用;在OnLayoutSize方法中告诉设计器活动的尺寸;在OnPaint方法中绘制活动的外观.上面的代码中,我们模仿命令行窗口的样子画了一个黑色的背景并将活动的Text属性用白色的字体输出.编译后的活动在设计器中的效果如下:

 

《WF编程》系列之39 - 自定义活动:继承法与活动组件

  当然,为了使设计器生效,我们需要为自定义活动关联

[ActivityValidator(typeof(ConsoleWriteValidator))]
[Designer(typeof(ConsoleWriteDesigner))]
publicclassConsoleWriteActivity:Activity
{
//
}

  设计器.

  本节的自定义活动非常简单.如果我们想要创建高级的自定义活动,我们还需要深入了解ActivityExecutionContext类的相关知识(如果感到眼熟就对了,我们在自定义活动的Execute方法中见过这个类)和活动生命周期的相关内容.

 

 
 

  这时,我们可以编译自定义活动,接下来创建一个新的工作流.打开工作流设计器,就可以在工具箱中(当然,我们需要引用包含这个活动的程序集)看到这个活动.如果我们将其拖拽到设计器中,就会发现这个活动看起来和基本类库的其它活动差不多.

《WF编程》系列之39 - 自定义活动:继承法与活动组件

  注意活动的Text属性也显示在了属性面板中(Misc分类下).我们可以通过System.ComponentModel和System.Workflow.ComponentModel命名空间中的特性来控制这个属性的设计时功能.举例来说,添加下面的代码到Text属性可以提供一个默认值,描述和属性的分类.

[DefaultValue("")]
[Description("Thetexttowritetotheconsole")]
[Category("Activity")]
publicstringText
{
get{return_text;}
set{_text=value;}
}

  特性并不是只能附加在属性上,我们还可以用特性来控制活动的行为和外观.

  5.5.2 活动组件我们可以关联活动组件(activity component)到我们的自定义活动,籍此来调整它的行为.两个重要的组件类型是活动设计器和活动验证器.我们使用特性来将组件和活动进行关联.而且很明显可以知道这些组件是可选的,因为前边的自定义活动范例就不需要使用任何组件.但是,许多优秀的自定义活动都或通过使用这些组件来增强设计器体验.

  在前面创建的自定义活动中,如果工作流设计者永远都不给Text属性分配值得话会发生什么状况呢?我们的ConsoleWrite活动在缺少有效的Text属性的情况下是不可用的,所以我们必须事先就假定编写者会犯这个错误.如果我们为自定义活动关联了验证器,那我们就可以给编写者一个恰当的反馈.


相关教程