65.9K
CodeProject 正在变化。 阅读更多。
Home

为 WF 自定义活动属性添加设计时支持

2009年6月5日

CPOL

5分钟阅读

viewsIcon

31901

downloadIcon

236

本文展示了我们如何轻松地为 WF 自定义活动属性添加设计时支持

引言

有时,当我们开发 WF 自定义活动时,我们希望拥有“属性设计时”支持,以加快属性的设置过程。如果您为一个自定义活动定义了一个属性,您可以提供一个自定义用户界面或类型编辑器,通过属性浏览器来编辑该属性的值。您可以构建一个名为“设计器”的类,该类可以在设计时管理组件或控件外观和行为的各个方面。

Using the Code

在这种情况下,我们将创建一个不太有用的自定义活动,只是为了展示属性设计时支持的工作原理。首先,我们将创建一个顺序工作流控制台应用程序。我们将使用此项目来测试我们的自定义活动。然后,我们必须添加一个包含自定义活动的 WorkFlow 库项目。

  1. 导航至 开始 | 所有程序 | Microsoft Visual Studio 2005 | Microsoft Visual Studio 2005。
  2. 选择 文件 | 新建 | 项目菜单命令。
  3. Visual Studio 将显示“新建项目”对话框。
  4. 选择 Visual C# | Workflow 项目类型。
  5. 选择 顺序工作流控制台应用程序。
  6. 右键单击解决方案。
  7. 选择 添加新项目。
  8. 单击 Workflow | Workflow Library。

此时,我们应该有一个类似这样的结果

FirstStep.JPG - Click to enlarge image

第一步是设置自定义活动的基础类。在此示例中,我们创建一个简单的自定义活动,因此我们必须将 System.Workflow.ComponentModel.Activity 设置为活动的基类。要做到这一点,只需单击活动属性窗口,然后单击基类属性。将会弹出一个窗口,然后选择 Activity 作为类型名称。

secondstep.JPG - Click to enlarge image

此时,活动的外观应如上图所示

thirdStep.JPG

现在我们准备开始向活动添加代码。在此示例中,我们创建一个打印文件路径属性到屏幕上的活动。这是一个完全无用的活动,但它是展示属性设计支持如何工作的绝佳示例。要开始,我们必须向我们的活动添加属性。在此情况下,我们只创建一个属性来包含文件的文件路径。在活动的 कोड 视图中,添加以下代码

using System.ComponentModel;
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;

namespace CustomActivityTester
{
    public partial class MyCustomActivity : System.Workflow.ComponentModel.Activity
    {
        public MyCustomActivity()
        {
            InitializeComponent();
        }
        public static DependencyProperty FilePathProperty =
		System.Workflow.ComponentModel.DependencyProperty.Register(
        "FilePath", typeof(string), typeof(MyCustomActivity));
        [Description("FilePath")]
        [Category("MyCustomActivity")]
        [Browsable(true)]

        [DefaultValueAttribute("False")]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public string FilePath
        {
            get
            {
                return ((string)base.GetValue(MyCustomActivity.FilePathProperty));
            }
            set
            {

                    base.SetValue(MyCustomActivity.FilePathProperty, value);
              }
        }
    }
}

现在我们可以将自定义活动添加到 Visual Studio 工具箱。我们还没有完成开发,但这样我们可以一步一步地看到它的工作原理。

  1. 右键单击工具箱。
  2. 选择“选择项”。
  3. 点击浏览选项卡。
  4. 从自定义活动项目文件夹中选择 myCustomLibrary.dll

此时,我们的活动应该出现在工具箱中

fourthstep.JPG

现在将活动拖放到工作流上。

fifthstep.JPG

选择活动并单击属性窗口。我们可以看到我们创建的 filePath 属性。Visual Studio 提供了设置属性的标准方法。我们可以通过代码设置它,或者我们可以创建一个属性或字段来绑定属性,然后我们可以通过代码再次设置它。

this.myCustomActivity1.FilePath = @"c:\MyFile.txt";

或者

sixthstep.JPG - Click to enlarge image

现在,如果我们想加快这项任务,我们可以为 FilePath 属性添加设计支持。也许在这种情况下,这并不是真正必要的,因为我们只需要设置一个文件路径,但这只是一个展示此过程如何工作的示例。属性设置的 UI 基于一个简单的 Winform,因此作为第一步,我们必须创建一个 Winform,我们在其中设计界面,并在其中添加代码来设置我们的属性。要做到这一点,右键单击 MyCustomLibrary 项目,然后向项目添加一个名为“FilePathDesignSupport”的新窗口窗体。

seventhstep.JPG

现在,为了避免用户在设置 FilePath 属性时关闭该窗口窗体并调整大小,我们需要设置几个窗体属性。

  1. 设置 ControlBox=false
  2. 设置 FormBorderStyle="FixedSingle"

现在我们可以开始设计窗口窗体,添加设置属性所需的控件

  1. 添加一个名为 btnCancel 的按钮
  2. 添加一个名为 btnOk 的按钮
  3. 添加一个名为 btnBrowse 的按钮
  4. 添加一个名为 lblFileName 的标签
  5. 添加一个名为 lblFileSelected 的标签

eightstep.JPG

将此代码添加到窗体的代码中

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyCustomLibrary
{
    public partial class FilePathDesignSupport: Form
    {
        public FilePathDesignSupport()
        {
            InitializeComponent();
        }
        private string _fileName = string.Empty;
        public string FileName
        {
            get
            {
                return _fileName;

            }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.lblFileSelected.Text = string.Empty;
            this._fileName = string.Empty;
            this.Close();
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ShowDialog();
        }

        private void openFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            if (string.IsNullOrEmpty(this.openFileDialog1.FileName) == false)
            {
                this.lblFileSelected.Text = this.openFileDialog1.FileName;
                this._fileName = this.lblFileSelected.Text;

            }
            else
            {
                this.lblFileSelected.Text = string.Empty;
                this._fileName = string.Empty;
            }
        }
    }
}

现在,用于设置 FilePath 属性的 UI 已经准备就绪。下一步是创建一个类来“管理”我们之前创建的 UI 的可视化,然后我们必须添加一个属性来告诉 Visual Studio 设计器,当用户想要设置属性时显示哪个控件。“UI 管理器”由一个继承自“UITypeEditor”的类表示。

下面是如何实现该类的

using System.ComponentModel;
using System;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using System.Drawing.Design;
using MyCustomLibrary;

namespace CustomActivityTester
{
    public partial class MyCustomActivity : System.Workflow.ComponentModel.Activity
    {
        public MyCustomActivity()
        {
            InitializeComponent();
        }
        public static DependencyProperty FilePathProperty =
		System.Workflow.ComponentModel.DependencyProperty.Register(
        "FilePath", typeof(string), typeof(MyCustomActivity));
        [Description("FilePath")]
        [Category("MyCustomActivity")]
        [Browsable(true)]
        [DefaultValueAttribute("False")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Editor(typeof(DriveEditor), typeof(UITypeEditor))]
        public string FilePath
        {
            get
            {
                return ((string)base.GetValue(MyCustomActivity.FilePathProperty));
            }
            set
            {
                    base.SetValue(MyCustomActivity.FilePathProperty, value);
            }
        }
        protected override ActivityExecutionStatus Execute
			(ActivityExecutionContext executionContext)
        {
        Console.WriteLine(string.Concat("The File path is: ",this.FilePath));
        return ActivityExecutionStatus.Closed;
        }
    }

    public class DriveEditor : UITypeEditor
    {
        public override System.Drawing.Design.UITypeEditorEditStyle
        GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            // We will use a window for property editing.
            return UITypeEditorEditStyle.Modal;
        }

        public override object EditValue(
        System.ComponentModel.ITypeDescriptorContext context,
        System.IServiceProvider provider, object value)
        {
            FilePathDesignSupport frm = new FilePathDesignSupport();

            //Show the UI to set up the property
            frm.ShowDialog();

            // Return the file name of the file selected.
            return frm.FileName;
        }

        public override bool GetPaintValueSupported(
        System.ComponentModel.ITypeDescriptorContext context)
        {
            // No special thumbnail will be shown for the grid.
            return false;
        }
    }
}

UITypeEditor 类最重要的一个方法是 EditValue 方法。它告诉 Visual Studio 当用户单击属性窗口以设置属性时应该做什么。在这种情况下,我们创建 FilePathDesignSupport 窗体的一个实例,然后将其显示出来。此方法必须返回一个对象,该对象表示我们正在设置的属性的值。在这种情况下,我们返回所选文件的文件路径。之后,我们必须将“FilePath”属性“绑定”到表示要显示的 UI 的类。要做到这一点,我们只需在 FilePath 属性中添加此属性 [Editor(typeof(DriveEditor), typeof(UITypeEditor))]。此时,一切都完成了。如果我们单击工作流中的自定义活动,然后单击 FilePath 属性,将显示 FilePath 窗体来设置属性。最后,我们可以覆盖 Activity 类的 Execute method。这是包含实现活动行为的代码的方法。在工作流执行活动时,运行时会调用此方法。在这种情况下,我们只是在屏幕上打印 FilePath 属性的值。

thelast.JPG - Click to enlarge image

正如我们在本文中看到的,为自定义活动属性添加设计支持相当容易。我们可以每次想加快属性设置过程时都使用这种方式,或者我们想帮助用户设置属性。

© . All rights reserved.