After having written your own custom activity which has some unique features, you will definitly want to write your own designer for it. There are however a lot of base classes to choose from depending on the type of custom activity you created.
For a simple activity however you will probably choose the standard ActivityDesigner class. Other classes at your disposal are the SequentialActivityDesigner and ParallelActivityDesigner. And if you really want to freak out you can choose the FreeformActivityDesigner. These however will be for later posts.
I will start with the simplest of all: the plain ActivityDesigner.
But first, in a GUI world where theming support is “the feature” to support: here are…
Designer Themes
Designer themes allow you to set a set of standard properties that will be used by the designers of your workflow. Or as the MSDN states it:
Designer themes define the look and feel of a designer. This includes any background styles, foreground styles, fonts, and icons defined for the designer.
In short: they provide, as all themes, a convenient way of having a common look and feel for your designers.
To allow you to customize some of the settings a few properties are assignable. Those can be set in the constructor to allow you to provide your own values. Most of them have to do with colors:
- BackColorEnd
- BackColorStart
- BorderColor
- …
There are also a lot of other properties which are readonly and thus are not customizable by setting them in the constructor.
Defining a theme is thus as simple as setting a few properties:
public class MyActivityTheme : ActivityDesignerTheme
{
public MyActivityTheme(WorkflowTheme theme)
: base(theme)
{
base.Initialize();
this.BackColorStart = Color.FromArgb(79, 63, 255);
this.BackColorEnd = Color.FromArgb(55, 202, 255);
this.BorderColor = Color.FromArgb(255, 63, 204);
}
}
During development I noticed that changing the designer theme of a designer doesn’t have any visual effect. I tought I was doing something wrong untill I came across this post:
ActivityDesignerTheme and VS restartI’m using Visual Studio 2008 and I still have this issue: apparently they didn’t look at it like they said they would … but the solution provided in the last third post does work:
Right click the activity in the designer view: the popup menu that appears has an item called “Select Custom Theme …”
insert picture SelectCustomeTheme
Click it and a dialog window will open. Click the Workflow Designers > Themes on the left side and at the right side select the “Operating System Color Theme”.
insert picture SelectCustomeThemeDialog
Repeat the same but now select the “Default Theme” et voila: your view should be updated. And now it’s waiting for Microsoft to solve the issue…
Custom Designers without drawing
Applying a theme to a designer is simple: you set the ActivityDesignerThemeAttribute to the designer class:
[ActivityDesignerTheme(typeof(MyActivityTheme))]
public class ThemedActivityDesigner : ActivityDesigner
{
}
Customization of your designer can be simple too. The ActivityDesigner class hase some properties which you can set in the constructor of your inheriting designer class or override in its implementation and which customize some of the visuals of your designer without the need for implementing your own drawing code.
If you look at a standard simple activity like the DelayActivity you can differentiate three basic areas on the designer surface:
- The Designer area: this is the complete area taken by the Designer in the Workflow designer
- The Image area: this area shows an image, mostly the designer icon from the toolbox, as a visual presentation of the type of designer
- The Text area: this area shows the text associated with the designer, which is mostly the name of the activity instance it represents
These areas and there content can be manipulated by following properties:
- ImageRectangle
- Image
- TextRectangle
- Text
- MinimumSize
- Size
Applying some of this knowledge in code gives us:
[ActivityDesignerTheme(typeof(MyActivityTheme))]
public class ThemedActivityDesigner : ActivityDesigner
{
private static Size TextSize = new Size(100, 50);
protected override void Initialize(System.Workflow.ComponentModel.Activity activity)
{
base.Initialize(activity);
this.Text = base.Text + " by HungryForKnowledge";
Assembly a = Assembly.GetExecutingAssembly();
Stream imgStream =
a.GetManifestResourceStream("HFK.CustomDesigners.DesignerImage.bmp");
this.Image = new Bitmap(imgStream);
}
protected override Rectangle TextRectangle
{
get
{
return new Rectangle(this.Bounds.Right - TextSize.Width,
this.Bounds.Top + (this.Bounds.Height - TextSize.Height) / 2,
TextSize.Width, TextSize.Height);
}
}
public override Size MinimumSize
{
get
{
return new Size(200, 100);
}
}
}
Which results in this view in the workflow designer of visual studio:
There is an important thing to notice here:
In the code you can see how I use the Bounds property for calculating the text rectangle. This is because the coordinates of the rectangle are not interpreted by the workflow designer as being releative to the avtivity designers surface. So if you specify a rectangle of Rectangle(0, 0, 10, 10), then the origin is not the left top of your designers surface, and the text will not be visible. The top left corner of your surface starts at the upper left corner of your designers Bounds property, and its with and height are those of the designers Bounds property. Thus specifying a 10 by 10 rectangle at the left top of your design surface requires following code:
new Rectangle(this.Bounds.Left, this.Bounds.Top,
10, 10)
Custom Designers and executing actions
If you have a custom designer for your activity you will likely want to peform actions with your designer that ultimately influence some property or behaviour of the activity associated with your designer.
You have two opportunities to execute actions:
- Execute actions in response to errors in the configuration of the custom activity
- Execute actions which somehow do something
The first type of actions are customizable through the DesignerActions property of the ActivityDesigner class. They result in an error glyph being shown which you can expand to show the available actions.
The second type of actions are configurable through the Verbs property and result in inserting entries in the popup menu shown by right clicking the designer surface.
Adding them is simple:
For the DesignerActions you override the DesignerActions property of the ActivityDEsigner class and return a collection filled with objects of type DesignerAction. Be carefull however: returning a non empty collection automatically adds the ConfigErrorGlyph (the red circle with an exclamation mark) to your activity designer. Remember, designer actions are used to signal and correct configuration errors. So you should only return a non-empty list if the activity associated with your designer has such errors.
In code:
protected override ReadOnlyCollection<DesignerAction> DesignerActions
{
get
{
List<DesignerAction> DesignerActionList =
new List<DesignerAction>();
DesignerActionList.Add(
new DesignerAction(this, 1, "There is an error!"));
return DesignerActionList.AsReadOnly();
}
}
protected override void OnExecuteDesignerAction(
DesignerAction designerAction)
{
if (designerAction.ActionId == 1)
MessageBox.Show(designerAction.Text);
}
Adding custom Verbs is equally simple: Override the Verbs poperty and return a collection of objects of type ActivityDesignerVerb to which you attached the eventhandler to handle the specified command.
In Code:
protected override ActivityDesignerVerbCollection Verbs
{
get
{
ActivityDesignerVerbCollection newVerbs =
new ActivityDesignerVerbCollection();
newVerbs.AddRange(base.Verbs);
newVerbs.Add(new ActivityDesignerVerb(this,
DesignerVerbGroup.General,
"Custom Action",
new EventHandler(CustomContextMenuEvent)));
return newVerbs;
}
}
private void CustomContextMenuEvent(object sender, EventArgs e)
{
MessageBox.Show("Perform some custom action");
}
Custom Designers and Glyphs
Glyphs allow you to somehow extend the visual presentation of your designer in a crosscutting-kind-of-manner. You can design a glyph and apply it to any activity designer that could use it. As such they are ideal for visually expressing conditions that are cross-cutting to activities.
An example is the standard provided ConfigErrorGlyph glyph. It draws a red circle around a white exclamation mark, indicating the activity is badly configured. Because most activities have properties that must have some correct value, this is ideal to be expressed by a glyph. The alternative would be for each activities designer to implement its own drawingcode for indicating the error and thus very likeley each activity designer having its own way of visualizing the error condition.
Microsoft provides you with some standard glyph implementations you can use:
- SelectionGlyph
- CommentGlyph
- ConfigErrorGlyph
- LockedActivityGlyph
- ReadOnlyActivityGlyph
- ShadowGlyph
As you can see from tehre names they most of them signal states which can be applied to various activities.
The ActivityDesigner class has a Glyph property which you can override and allows you to attach some glyphs to your designer class.
In Code:
protected override ActivityDesignerGlyphCollection Glyphs
{
get
{
ActivityDesignerGlyphCollection glyphs =
new ActivityDesignerGlyphCollection();
glyphs.AddRange(base.Glyphs);
glyphs.Add(new ShadowGlyph());
return glyphs;
}
}
There is however a caveat with this property: the workflow designer uses this property to know which glyphs to show and if you override it without calling the base-class version you will lose the automtic addition of glyphs, like the ConfigErrorGlyph when returning a non-empty collection from the DesignerActions property.
Designer – Activity interaction
Of course, if you have a designer for your activity, you will probably want to do something with your activity in your designer. For this, the designer has an Activity property which gives you access to the activity being designed.
Downloads
Links
How to Write a Designer Component for Custom Workflow Activity
Adding SmartTag Verbs to an Activity Designer
Windows workflow foundation animated activity designer source