• WWF3自定义活动<第八篇>


      WWF提供了对原有活动进行扩展以及自定义新活动的功能,用户可以通过"Workflow Activity Library"创建和开发自定义活动。

      

    一、自定义活动类型

      默认情况下,创建的自定义活动是继承"System.Workflow.Activities.SequenceActivity"父类的。该类型自定义活动的外观是由一个Sequence顺序类型的容器构成的,用户可以在Sequence活动内添加其他子活动。

      

      属性如下:

      

      代码如下:

    namespace ActivityLibrary1
    {
        public partial class Activity1: SequenceActivity
        {
            public Activity1()
            {
                InitializeComponent();
            }
        }
    }

      活动的自定义方式:

    继承的类型 说明
    System.Workflow.Activities.SequenceActivity 自定义顺序类型
    System.Workflow.ComponentModel.CompositeActivity 自定义补偿类型的自定义活动
    System.Workflow.Activities.CallExternalMethodActivity 在CallExternalMethod活动基础上封装一些额外的功能
    System.Workflow.Activities.HandleExternalEventActivity 在HandleExternalEvent活动基础上封装一些额外的功能
    System.Workflow.ComponentModel.Activity 自定义"ComponentModelActivity"类型的活动

      如自定义补偿类型活动:

        public partial class Activity1 : CompositeActivity
        {
            public Activity1()
            {
                InitializeComponent();
            }
        }

      利用WWF开发出来的自定义活动使用起来也非常简单,在同一个解决方案下开发的自定义活动,只要编译成功后就可以在"工具栏"中看到并可以直接使用。

    二、自定义普通属性

      在WWF中可以通过"DependencyProperty"来存储和管理自定义活动的属性。

      首先定义一个"DependencyProperty"属性并且利用它的"Register"方法进行注册。在注册时需要指明该"Dependency Property"属性所存储的"属性名称"、"属性的类型"、以及该属性"所在自定义活动的名称",还可以利用"PropertyMetadata"来为属性定义默认值。

    namespace ActivityLibrary1
    {
        public partial class Activity1 : System.Workflow.ComponentModel.Activity
        {
         //将自定义活动"CustomActivity"中的一个字符类型属性"Paral"注册到"DependencyProperty"类型的属性"ParalProperty"中
    public static DependencyProperty ParalProperty = DependencyProperty.Register("Paral", typeof(System.String), typeof(Activity1)); public string Paral { get { return ((string)(base.GetValue(Activity1.ParalProperty))); } set { base.SetValue(Activity1.ParalProperty, value); } } public Activity1() { InitializeComponent(); } } }

      新建一个顺序工作流项目,可以看到工具箱多了选项,拖入工作流后还有一个叫Paral的属性。

      

      

      自定义活动的特性:

    特性名称 说明
    DescriptionAttribute 提示信息[Description("打印一个字符串!")]
    BrowsableAttribute  是否在属性窗口显示[Browsable(true)]

      当然,用户可以通过"DependencyProperty"属性的"PropertyMetadata"方法来为其设置默认值。

    public static DependencyProperty ParalProperty = DependencyProperty.Register("Paral", typeof(System.String), typeof(Activity1),new PropertyMetadata("默认赋的值!"));

      从新编译后,可以看到刚刚拖入进来的控件已经有了默认值。

      

    三、自定义事件类型属性

      除了上面提到的普通属性外,还有一种事件属性。用户可以通过该属性创建相应的事件。例如Code活动的"ExecuteCode"属性就能够用来创建一个事件,开发人员可以在该事件中执行相应的业务操作。事件属性的创建与前面类似,只是属性类型是"event"类型。

      自定义一个活动如下:

    namespace ActivityLibrary1
    {
        [ToolboxItemAttribute(typeof(ActivityToolboxItem))]
        public partial class Activity1 : System.Workflow.ComponentModel.Activity
        {
            //将自定义活动"CustomActivity"中的一个字符类型属性"Paral"注册到"DependencyProperty"类型的属性"ParalProperty"中
            public static DependencyProperty PrintEvent = DependencyProperty.Register("Print", typeof(EventHandler), typeof(Activity1));
            public event EventHandler Print
            {
                add
                {
                    base.AddHandler(PrintEvent, value);
                }
                remove
                {
                    base.RemoveHandler(PrintEvent, value);
                }
            }
         //用户必须重载父类的"Execute"方法,并通过"RaiseEvent"来加载相应"DependencyProperty"属性,该属性才能执行
            protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
            {
                base.RaiseEvent(PrintEvent, this, EventArgs.Empty);
                return ActivityExecutionStatus.Closed;
            } 
    
            public Activity1()
            {
                InitializeComponent();
            }
        }
    }

      新建一个工作流,拉入控件后,显示如下: 

      

    四、自定义活动的验证方式

      在使用WWF进行工作流设计时,如果某些属性没有设置或设置错误,那么WWF将会给出相应的提示,在进行自定义活动时同样可以实现对属性值进行验证的功能。

      首先建立一个专门用于对属性值进行验证的类,然后继承自"System.Workflow.ComponentModel.Compiler.ActivityValidatoe",并重载"ValidationErrorCollection"方法。

      在该方法中用户可以对所需要验证的属性进行逐一判断,如果验证失败,则可以通过ValidationError错误将属性收集,最后一起返回给用户。

      下面给出一个验证属性的示例:

    namespace ActivityLibrary1
    {
        [ActivityValidator(typeof(CustomActivityValidator))]
        public partial class Activity1 : System.Workflow.ComponentModel.Activity
        {
            //将自定义活动"CustomActivity"中的一个字符类型属性"Paral"注册到"DependencyProperty"类型的属性"ParalProperty"中
            public static DependencyProperty ParalProperty = DependencyProperty.Register("Paral", typeof(System.String), typeof(Activity1), new PropertyMetadata("你好!"));
            public string Paral
            {
                get
                {
                    return ((string)(base.GetValue(Activity1.ParalProperty)));
                }
                set
                {
                    base.SetValue(Activity1.ParalProperty, value);
                }
            }
    
            public Activity1()
            {
                InitializeComponent();
            }
        }
    
        //创建一个类,继承自ActivityValidator
        public class CustomActivityValidator : System.Workflow.ComponentModel.Compiler.ActivityValidator
        {
            //重写ValidationErrorCollection方法
            public override ValidationErrorCollection ValidateProperties(ValidationManager manager, object obj)
            {
                ValidationErrorCollection validationErrors = base.ValidateProperties(manager, obj);
    
                Activity1 activity = obj as Activity1;
    
                if (activity != null)
                {
                    //当属性为空时,添加到validationErrors
                    if (String.IsNullOrEmpty(activity.Paral))
                    {
                        validationErrors.Add(ValidationError.GetNotSetValidationError(Activity1.ParalProperty.Name));
                    }
                    //当属性不包含感叹号时,添加到validationErrors
                    else if (!activity.Paral.Contains("!"))
                    {
                        validationErrors.Add(new ValidationError("没有包含感叹号啊,大哥!", 1, false, Activity1.ParalProperty.Name));
                    }
                }
                return validationErrors;
            }
        }
    }

      当我们新建一个工作流,再使用这个控件,但是属性值不包含感叹号时。生成报如下错误:

      

      

    五、自定义活动的外观

      对于自定义的活动,WWF支持自定义活动的图标,只需将一个图片加载到自定义活动的项目中,然后将该图片的属性"Build Action"设置为"Embedded Resource"(生成操作设为嵌入的资源)。最后在自定义活动类的上面添加以下标识。

    namespace ActivityLibrary1
    {
        [ToolboxBitmap(typeof(Activity1), "pic.1.bmp")] //设置自定义图标
        [Designer(typeof(CusActivityDesigner), typeof(IDesigner))]  //设置自定义样式
        public partial class Activity1 : System.Workflow.ComponentModel.Activity
        {
            public Activity1()
            {
                InitializeComponent();
            }
        }
       //自定义样式类
        public class CustomTheme : ActivityDesignerTheme
        {
            public CustomTheme(WorkflowTheme theme) : base(theme)
            {
                this.BorderColor = Color.Red; //边框红色
                this.BackColorStart = Color.White; //渐变从白色开始
                this.BackColorEnd = Color.Blue; //渐变从蓝色结束
            }
        }
    
        [ActivityDesignerThemeAttribute(typeof(CustomTheme))]
        public class CusActivityDesigner : ActivityDesigner
        {
        }
    }

      工作流显示效果如下:

      

    六、综合示例

      模拟一个计算器,然后将其中的计算功能作为一个自定义活动进行开发,然后在工作流中进行使用。

      1、创建自定义活动

    namespace ActivityLibrary1
    {
        [ActivityValidator(typeof(CustomActivityValidator))]
        public partial class CustomActivity : System.Workflow.ComponentModel.Activity
        {
            public static DependencyProperty Para1Property = DependencyProperty.Register("Para1", typeof(System.Int32), typeof(CustomActivity), new PropertyMetadata(0));
            public static DependencyProperty Para2Property = DependencyProperty.Register("Para2", typeof(System.Int32), typeof(CustomActivity), new PropertyMetadata(10));
            public static DependencyProperty OperProperty = DependencyProperty.Register("Oper", typeof(System.String), typeof(CustomActivity), new PropertyMetadata("+"));
    
            public static DependencyProperty InvokedEvent = DependencyProperty.Register("Invoked", typeof(EventHandler<CustomActivityEventArgs>), typeof(CustomActivity));
    
            public CustomActivity()
            {
                InitializeComponent();
            }
    
            [DescriptionAttribute("运算符")]
            [BrowsableAttribute(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public string Oper
            {
                get
                {
                    return ((string)(base.GetValue(CustomActivity.OperProperty)));
                }
                set
                {
                    base.SetValue(CustomActivity.OperProperty, value);
                }
            }
    
    
            [DescriptionAttribute("整型数字")]
            [BrowsableAttribute(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public int Para1
            {
                get
                {
                    return ((int)(base.GetValue(CustomActivity.Para1Property)));
                }
                set
                {
                    base.SetValue(CustomActivity.Para1Property, value);
                }
            }
    
    
            [DescriptionAttribute("整型数字")]
            [BrowsableAttribute(true)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            public int Para2
            {
                get
                {
                    return ((int)(base.GetValue(CustomActivity.Para2Property)));
                }
                set
                {
                    base.SetValue(CustomActivity.Para2Property, value);
                }
            }
    
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
            [BrowsableAttribute(true)]
            [Category("Handlers")]
            public event EventHandler<CustomActivityEventArgs> Invoked
            {
                add
                {
                    base.AddHandler(CustomActivity.InvokedEvent, value);
                }
                remove
                {
                    base.RemoveHandler(CustomActivity.InvokedEvent, value);
                }
            }
    
            protected override ActivityExecutionStatus Execute(ActivityExecutionContext context)
            {
                CustomActivityEventArgs e = new CustomActivityEventArgs();
    
                if (Oper == "+")
                    e.Result = (this.Para1 + this.Para2).ToString();
                else if (Oper == "-")
                    e.Result = (this.Para1 - this.Para2).ToString();
                else if (Oper == "*")
                    e.Result = (this.Para1 * this.Para2).ToString();
                else if (Oper == "/")
                    e.Result = (this.Para1 / this.Para2).ToString();
    
                this.RaiseGenericEvent<CustomActivityEventArgs>(InvokedEvent, this, e);
    
                return ActivityExecutionStatus.Closed;
            }
        }
    
        public class CustomActivityEventArgs : EventArgs
        {
            private string result;
    
            public string Result
            {
                get { return result; }
                set { result = value; }
            }
        }
    
        public class CustomActivityValidator : System.Workflow.ComponentModel.Compiler.ActivityValidator
        {
            public override ValidationErrorCollection ValidateProperties(ValidationManager manager, object obj)
            {
                ValidationErrorCollection validationErrors = base.ValidateProperties(manager, obj);
    
                CustomActivity activity = obj as CustomActivity;
    
                if (activity != null)
                {
                    if (String.IsNullOrEmpty(activity.Oper))
                    {
                        validationErrors.Add(ValidationError.GetNotSetValidationError(CustomActivity.OperProperty.Name));
    
                    }
                    if (activity.Para2 == 0)
                    {
                        validationErrors.Add(new ValidationError("除数不能为0", 1, false, CustomActivity.Para2Property.Name));
                    }
                }
                return validationErrors;
            }
        }
    }

      2、新建一个工作流,里面就一个自定义活动

      

      代码如下:

    namespace WorkflowConsoleApplication1
    {
        public sealed partial class Workflow1 : SequentialWorkflowActivity
        {
            private string oper;
            public string Oper
            {
                get { return oper; }
                set { oper = value; }
            }
            private int para1;
            public int Para1
            {
                get { return para1; }
                set { para1 = value; }
            }
            private int para2;
            public int Para2
            {
                get { return para2; }
                set { para2 = value; }
            }
            public Workflow1()
            {
                InitializeComponent();
            }
            private void Invoked(object sender, ActivityLibrary1.CustomActivityEventArgs e)
            {
                MessageBox.Show(e.Result);
            }
        }
    }

       注意要设置好这些属性,否则可能运行不成功:

      

      全部绑定到自定义控件的对应属性。

      3、新建一个Winform项目

      界面如下:

      

      代码如下:

        public partial class Form1 : Form
        {
            private WorkflowRuntime wfRuntime = null;
            private WorkflowInstance wfInstance = null;
    
            public Form1()
            {
                InitializeComponent();
    
                wfRuntime = new WorkflowRuntime();
                wfRuntime.StartRuntime();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
    
                Dictionary<string, object> parameters = new Dictionary<string, object>();
                parameters.Add("Oper", this.comboBox1.Text);
                parameters.Add("Para1", Convert.ToInt32(this.textBox1.Text));
                parameters.Add("Para2", Convert.ToInt32(this.textBox2.Text));
    
                wfInstance = wfRuntime.CreateWorkflow(typeof(CustomActivity.Workflow1),parameters);
    
                wfInstance.Start();
            }
        }

      效果如下:

      

  • 相关阅读:
    Array.sort源码
    Linkedlist源码
    最大公约数 2.7
    腾讯笔试题
    腾讯2014校园招聘笔试题
    指针问题
    JavaScript 日历
    QT 初阶 第二章 创建对话框(查找对话框实例)
    QT 初阶 1.3 节 控件的几何排列
    “项目中的问题”
  • 原文地址:https://www.cnblogs.com/kissdodog/p/3967697.html
Copyright © 2020-2023  润新知