Voici le rendu du workflow basique. Celui-ci se compose de deux activités. L'une génère une path qui sera visible en output et sera utilisé en input dans la seconde activité.
La création d'une activité est simple. Il suffit d'hériter par exemple de Activity et d'overrider la méthode Execute. Pour ce qui est des propriétés qui seront utiliser en "in"/"out", il faut utiliser le même principe que pour windows presentation foundation. On utilise l'objet DependencyProperty. Celui-ci a le même nom que sous WPF mais il ne s'agit pas de la même classe. Les deux classes se trouvent dans un namespace (et assembly) différent. L'utilisation de DependencyProperty offre également la possibilité de spécifier une valeur par défaut pour la propriété etc.
  1. Activité de génération du path
  2. [Designer(typeof(GenerateNameActivityDesigner))]
    [ToolboxBitmap(typeof(GenerateNameActivity), "gnome-fs-directory.png")]
    public partial class GenerateNameActivity : System.Workflow.ComponentModel.Activity
    {
        public static DependencyProperty UserNameGeneratedProperty =
                DependencyProperty.Register("UserNameGenerated",
                typeof(System.String),
                typeof(GenerateNameActivity));
    
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        [BrowsableAttribute(true)]
        [DescriptionAttribute("UserNameGenerated")]
        [CategoryAttribute("UserNameGenerated Property")]
        public string UserNameGenerated
        {
            get
            {
                return ((string)(base.GetValue(UserNameGeneratedProperty)));
            }
            set
            {
                base.SetValue(UserNameGeneratedProperty, value);
            }
        }
    
    	public GenerateNameActivity()
    	{
    		InitializeComponent();
    	}
    
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            UserNameGenerated = Path.GetTempFileName();
            return ActivityExecutionStatus.Closed;
        }
    }
    
  3. Activité d'affichage du path généré
  4. public partial class DisplayActivity : System.Workflow.ComponentModel.Activity
    {
        public static DependencyProperty UserNameProperty =
            DependencyProperty.Register("UserName",
            typeof(System.String),
            typeof(DisplayActivity));
    
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        [BrowsableAttribute(true)]
        [DescriptionAttribute("Username")]
        [CategoryAttribute("Username Property")]
        public string UserName
        {
            get
            {
                return ((string)(base.GetValue(UserNameProperty)));
            }
            set
            {
                base.SetValue(UserNameProperty, value);
            }
        }
    
    	public DisplayActivity()
    	{
    		InitializeComponent();
    	}
    
        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            Console.WriteLine("Path generated : {0}", UserName);
            return ActivityExecutionStatus.Closed;
        }
    }
    
La seconde partie de ce post concerne la customisation du rendu de l'activité dans le workflow. Ainsi, pour faire propre ... il faut implémenter les classes de thème (ci-dessous) ... et les assigner en attribut au dessus de l'activité.
public sealed class GenerateNameActivityDesignerTheme : ActivityDesignerTheme
{
    public GenerateNameActivityDesignerTheme(WorkflowTheme theme)
        : base(theme)
    {
        this.BackColorStart = Color.LightGreen;
        this.BackColorEnd = Color.Green;
    }

}

[ActivityDesignerTheme(typeof(GenerateNameActivityDesignerTheme))]
public sealed class GenerateNameActivityDesigner : ActivityDesigner
{
    protected override void Initialize(Activity activity)
    {
        base.Initialize(activity);
    }
}
Après création de ces thèmes, le rendu du workflow est différent ;-)
Vous pouvez télécharger les sources via ce lien.