博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
坚持学习WF(5):自定义活动(CustomActivity)
阅读量:6223 次
发布时间:2019-06-21

本文共 7404 字,大约阅读时间需要 24 分钟。

当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自己的活动。工作流引擎并不会区别一个活动是WF提供的标准活动还是第三方自定义活动.自定义活动有两种方式,组合方式和继承方式.组合是你从工具箱里拖出你需要的活动将他们组织在一起形成一个新的活动;使用继承的方式我们需要编写一个类,该类可以继承Activity类或其他的类,比如SequenceActivity等.组合的方式比较简单,下面我们就使用继承的方式来自定义一个活动。

实现逻辑 

我现在要完成一个这样的活动,我去银行存钱,当我存钱的时候会有一个友情提示,提示我保护好您的密码,然后如果存钱的数额小于1000就提示说钱太少,不能存,如果大于1000就提示存款成功.

下面我们就新建一个Activity名字叫CreditActivity,我们在它的属性里将Base类设置为Activity,这个基类已经足够了,然后我们增加一个依赖属性AccountProperty来表示存款数额,代码如下:

public 
static DependencyProperty AccountProperty  = System.Workflow.ComponentModel.DependencyProperty.Register( 
           
"
Account
"
typeof(Int32), 
typeof(CreditActivity)); 
       [Description(
"
存款数额
")] 
       [Category(
"
自定义活动示例
")] 
       [Browsable(
true)] 
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
       
public Int32 Account 
       { 
           
get 
           { 
               
return ((Int32)(
base.GetValue( 
                   CreditActivity.AccountProperty))); 
           } 
           
set 
           { 
               
base.SetValue(CreditActivity.AccountProperty, value); 
           } 
       }

然后在增加一个依赖事件BeCarefulEvent ,用于当用户存钱的提示它注意保护密码,代码如下:

public 
static DependencyProperty BeCarefulEvent = DependencyProperty.Register(
"
BeCareful
"
typeof(EventHandler<CustomActivityEventArgs>), 
typeof(CreditActivity)); 
       [DescriptionAttribute(
"
友情提示:注意保护密码
")] 
       [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] 
       [BrowsableAttribute(
true)] 
       [Category(
"
Handlers
")] 
       
public 
event EventHandler<CustomActivityEventArgs> BeCareful 
       { 
           add 
           { 
               
base.AddHandler(CreditActivity.BeCarefulEvent, value); 
           } 
           remove 
           { 
               
base.RemoveHandler(CreditActivity.BeCarefulEvent, value); 
           } 
       }

然后我们要实现我们的逻辑代码,我们需要重写Activity类的Execute方法,并在该方法中引发BeCarefulEvent事件。这个方法返回一个ActivityExecutionStatus,代表当前Activity实例的运行状态的枚举值,Return.base.Execute(executionContext)这个默认的返回ActivityExecutionStatus.Closed. ActivityExecutionContext是提供活动运行环境的相关信息.代码如下

protected 
override ActivityExecutionStatus Execute( ActivityExecutionContext executionContext) 
        { 
            CustomActivityEventArgs customActivityEventArgs = 
new CustomActivityEventArgs(
this.Description); 
            
this.RaiseGenericEvent<CustomActivityEventArgs>(BeCarefulEvent, 
this, customActivityEventArgs); 
            
//
simulate an account lookup 
            
if (Account <= 
1000
            { 
                Console.WriteLine(
"
钱也太少了吧,要大于1000的
"); 
            } 
            
else 
            { 
                Console.WriteLine(
"
存好了,下回多存点啊
"); 
            } 
            
return 
base.Execute(executionContext); 
        }

下面我就在Workflow中设置它的存款数额为600,和BeCarefulEvent事件,如下图:

(图 一)

BeCarefulEvent的事件处理程序onBeCareful的代码如下:

private 
void onBeCareful(
object sender, CaryActivityLibrary.CustomActivityEventArgs e) 
        { 
            Console.WriteLine(e.ActivityDescription+
"
:小心保护密码
");
            Console.WriteLine()
         }

现在我们来运行我们的程序:

提高设计体验

上面我们只是简单的实现我们的逻辑,但很多时候并不是逻辑是最重要的,我们的设计体验同样重要,下面我们说说自定义活动中怎样才能提高设计的体验。

自定义活动图标

不知道你注意到没有,在(图一)中的我们自定义的活动前的图标很好看,这个也是我自己选的,只要下面的一行代码就可以实现:

[ToolboxBitmap(
typeof(CreditActivity), 
"
Test.png
")] 
public 
partial 
class CreditActivity : System.Workflow.ComponentModel.Activity{
dot.gif..}

注意图片的生成操作属性应该设置为“嵌入的资源”,如下图:

自定义活动主题

(图一)中活动的主题的样式也是我们自己可以定制的,我们新建一个CreditActivityTheme类,继承自ActivityDesignerTheme,在其构造函数中设置我们想要的样式,代码如下:

public 
class CreditActivityTheme : ActivityDesignerTheme 
    { 
        
public CreditActivityTheme(WorkflowTheme theme) 
            : 
base(theme) 
        { 
            
this.BackColorStart = Color.LightSteelBlue; 
            
this.BackColorEnd = Color.Gainsboro; 
            
this.BorderStyle = DashStyle.DashDot; 
            
this.BorderColor = Color.DarkRed; 
            
this.BackgroundStyle = LinearGradientMode.ForwardDiagonal;            
        } 
    }

其实Visual Studio本身也提供了强大的主题设计器。

自定义活动行为

我们不但可以设置样式,还可以增加以下的行为来用另一种方式设置我们的存款数额,如下图:

要实现上面的并不难,你需要定义一个CreditActivityDesigner类继承自ActivityDesigner,代码如下:

[ActivityDesignerTheme(
typeof(CreditActivityTheme))] 
    
public 
class CreditActivityDesigner : ActivityDesigner 
    { 
        
protected 
override System.Collections.ObjectModel.ReadOnlyCollection<DesignerAction> DesignerActions 
        { 
            
get 
            { 
                List<DesignerAction> list = 
new List<DesignerAction>(); 
                
foreach (DesignerAction temp 
in 
base.DesignerActions) 
                { 
                    list.Add(
new DesignerAction(
this, temp.ActionId, temp.Text)); 
                } 
                
return list.AsReadOnly(); 
            } 
        } 
        
protected 
override ActivityDesignerVerbCollection Verbs 
        { 
            
get 
            { 
                ActivityDesignerVerbCollection NewVerbs = 
new ActivityDesignerVerbCollection(); 
                NewVerbs.AddRange(
base.Verbs); 
                ActivityDesignerVerb menu = 
new ActivityDesignerVerb(
this, DesignerVerbGroup.View, 
"
设置存款数额啦
"
new EventHandler(menu_click)); 
                NewVerbs.Add(menu); 
                
return NewVerbs; 
            } 
        } 
 
        
private 
void menu_click(
object sender, EventArgs e) 
        { 
            
using (CreditActivitySet wf = 
new CreditActivitySet()) 
            { 
                
int v = (
int)
this.Activity.GetValue(CreditActivity.AccountProperty); 
                wf.Value = v.ToString(); 
                wf.ShowDialog(); 
                
this.Activity.SetValue(CreditActivity.AccountProperty, Convert.ToInt32(wf.Value)); 
            } 
        } 
    }

CreditActivitySet 是设置数额的window form。

自定义活动验证器

你可能还会记得当你拖动一个CodeActivity的时候,如果你没有设置它的ExecuteCode属性,它会有一个叹号,编译不能通过。下面我们也来实现同样的效果,如果我们没有设置存款数额Account,我们就也出现类似的提示,我们定义一个CreditActivityValidator类继承自ActivityValidator。代码如下:

public 
class CreditActivityValidator : ActivityValidator 
    { 
        
public 
override ValidationErrorCollection Validate( 
            ValidationManager vManager, 
object obj) 
        { 
            ValidationErrorCollection errors = 
base.Validate(vManager, obj); 
            
if (obj 
is CreditActivity) 
            { 
                CreditActivity creditActivity = obj 
as CreditActivity; 
                
if (creditActivity.Parent != 
null
                { 
                    
if (creditActivity.Account == 
0
                    { 
                        errors.Add( 
                            ValidationError.GetNotSetValidationError( 
                                
"
Account
")); 
                    } 
                } 
            } 
            
return errors; 
        } 
    }

效果如下图:

我们是通过以下特性来应用到我们自定义的活动上的 : 

 [ActivityValidator(
typeof(CreditActivityValidator))] 
    [Designer(
typeof(CreditActivityDesigner))] 
    
public 
partial 
class CreditActivity : System.Workflow.ComponentModel.Activity    {
dot.gif}

定制工具箱行为

我们还可以定制工具箱行为,就是当我们把一个活动从工具箱拖到工作流设计器上时所做的动作,我另外定义了一个CaryCompositeActivity 活动,继承自 SequenceActivity,这样就可以包含子活动了,当我们把CaryCompositeActivity 拖到工作流设计器时,我们给他添加一些默认的子活动,我们编写了一个CaryCompositeActivityToolboxItem 并继承自ActivityToolboxItem,代码如下:

[Serializable] 
   
public 
class CaryCompositeActivityToolboxItem : ActivityToolboxItem 
   { 
       
public CaryCompositeActivityToolboxItem() 
           : 
base() 
       {    } 
       
public CaryCompositeActivityToolboxItem( 
           SerializationInfo info, StreamingContext context) 
               : 
base(info, context) 
       { } 
       
protected 
override IComponent[] CreateComponentsCore(IDesignerHost host) 
       { 
           CaryCompositeActivity activity = 
new CaryCompositeActivity(); 
           IfElseActivity ifElse = 
new IfElseActivity(
"
ifElse1
"); 
           ifElse.Activities.Add(
new IfElseBranchActivity(
"
ifFirstCondition
")); 
           ifElse.Activities.Add(
new IfElseBranchActivity(
"
ifSecondCondition
")); 
           ifElse.Activities.Add(
new IfElseBranchActivity(
"
elseBranch
")); 
           activity.Activities.Add(ifElse); 
           
return 
new IComponent[] { activity }; 
       } 
   }

然后我们在写一个类来实现该活动只能添加指定的子活动,我们编写一个类CaryCompositeActivityDesigner 继承自SequentialActivityDesigner,代码如下:

public 
class CaryCompositeActivityDesigner : SequentialActivityDesigner 
    { 
        
private 
static List<Type> allowedActivityTypes = 
new List<Type>(); 
        
static CaryCompositeActivityDesigner() 
        { 
            allowedActivityTypes.Add(
typeof(IfElseActivity)); 
            allowedActivityTypes.Add(
typeof(IfElseBranchActivity)); 
            allowedActivityTypes.Add(
typeof(CodeActivity)); 
        } 
        
public 
override 
bool CanInsertActivities(HitTestInfo insertLocation, 
            ReadOnlyCollection<Activity> activitiesToInsert) 
        { 
            Boolean result = 
true
            
if (activitiesToInsert != 
null
            { 
                
foreach (Activity activity 
in activitiesToInsert) 
                { 
                    result = (allowedActivityTypes.Contains(activity.GetType())); 
                    
if (result == 
false
                    { 
                        
break
                    } 
                } 
            } 
            
return result; 
        } 
    }

效果如下图:

allowedActivityTypes 集合中我们指定了只能添加 IfElseActivity,IfElseBranchActivity,CodeActivity三种活动,但是在它的子活动IfElseBranchActivity中就没有这个限制了,因为IfElseBranchActivity也有自己的设计器。

代码下载:上一篇: 
下一篇:

本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2008/04/13/CustomActivity.html,如需转载请自行联系原作者

你可能感兴趣的文章
Myeclipse代码提示及如何设置自动提示
查看>>
c/c++中保留两位有效数字
查看>>
ElasticSearch 2 (32) - 信息聚合系列之范围限定
查看>>
VS2010远程调试C#程序
查看>>
[MicroPython]TurniBit开发板DIY自动窗帘模拟系统
查看>>
由String类的Split方法所遇到的两个问题
查看>>
Python3.4 12306 2015年3月验证码识别
查看>>
从Handler.post(Runnable r)再一次梳理Android的消息机制(以及handler的内存泄露)
查看>>
windows查看端口占用
查看>>
strongswan ikev2 server on ubuntu 14.04
查看>>
Yii用ajax实现无刷新检索更新CListView数据
查看>>
JDBC的事务
查看>>
Io流的概述
查看>>
App 卸载记录
查看>>
JavaScript变量和作用域
查看>>
JS 对象机制深剖——new 运算符
查看>>
10大托管国家和5大危险电子邮件主题
查看>>
Go嵌入类型及内部提升样例
查看>>
《软件工艺师:专业、务实、自豪》一3.7.4 软件工艺社团
查看>>
jQuery获取数组对象的值
查看>>