Il designer di WF integrato in Visual Studio 2008 (o 2005 munito delle relative 'extensions') utilizza le classi del namespace System.Workflow.ComponentModel.Design per il controllo del rendering delle attività. In realtà il layout di una attività semplice (Activity) o composta (CompositeActivity) può essere personalizzato in maniera molto facile.
Anzitutto, il designer sfrutta due classi base: ActivityDesigner e ActivityDesignerTheme. La prima si occupa di gestire "come" un' attività verrà visualizzata nel designer (es. dimensioni, forma, editing etc.), mentre la seconda viene prettamente utilizzata per impostare il tema da associare al designer (es. colori, bordi etc.). Nello stesso namespace esistono inoltre diverse specializzazioni della classe base ActivityDesigner come CompositeActivityDesigner, SequentialActivityDesigner, ParallelActivityDesigner etc.
Quindi, estendendo opportunamente metodi e proprietà della classe base che scegliamo, possiamo apportare interessanti personalizzazioni.Vediamo un semplice esempio.
Creiamo una classe MyCustomActivityDesignerTheme ereditata da ActivityDesignerTheme per definire il nostro tema.
using System.Workflow.ComponentModel.Design;
namespace MyCustomActivityLibrary
{
internal sealed class MyCustomActivityDesignerTheme : ActivityDesignerTheme
{
public MyCustomActivityDesignerTheme(WorkflowTheme theme) : base(theme)
{
base.Initialize();
this.BackColorStart = System.Drawing.Color.Orange;
this.BackColorEnd = System.Drawing.Color.OrangeRed;
this.BorderColor = System.Drawing.Color.Red;
this.BorderStyle = System.Drawing.Drawing2D.DashStyle.Solid;
}
}
}
Quindi, ci concentriamo sul comportamento del rendering del designer implementando una classe MyCustomActivityDesigner derivata da ActivityDesigner, specificando che il tema da utilizzare sia quello sopra definito (MyCustomActivityDesignerTheme)
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel;
using System.Drawing;
namespace MyCustomActivityLibrary
{
[ActivityDesignerTheme(typeof(MyCustomActivityDesignerTheme))]
internal sealed class MyCustomActivityDesigner : ActivityDesigner
{
protected override void Initialize(Activity activity)
{
base.Initialize(activity);
this.Text = "[MyCustomActivity] " + activity.Name;
}
protected override Rectangle TextRectangle
{
get { ... }
}
protected override Rectangle ImageRectangle
{
get { ... }
}
protected override void OnPaint(ActivityDesignerPaintEventArgs e)
{ ... }
}
}
Osserviamo come l'overriding di metodi e proprietà della classe ActivityDesigner (qui la lista completa) ci permette di modificare particamente ogni aspetto del rendering. Nel nostro stupidissimo esempio è stata semplicemente estesta la logica del metodo Initialize(...) per anteporre il prefisso "[MyCustomActivity]" al nome dell' attività di interesse.
L'ultimo step è ovviamente l'associazione del designer realizzato nei confronti di una nostra attività custom (ShippingActivity) tramite l'impostazione dell' attributo Designer.
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace MyCustomActivityLibrary
{
[Designer(typeof(MyCustomActivityDesigner))]
public class ShippingActivity : Activity
{ ... }
}
Il risultiamo che otteniamo è il seguente:
Technorati tags: Workflow Foundation WF