In VS2010 Beta 2 you can associate your own activity designer with a custom activity in one of two ways:

Using System.ComponentModel.DesignerAttribute on the custom activity

Implementing System.Activities.Presentation.Metadata.IRegisterMetadata, using the Register() method to set up the association at run-time

It should be obvious that option (1) couples your custom activity directly to a specific designer. While not ideal, in many cases this is sufficient. But, there are some scenarios that require a looser coupling. For example, I may want to choose one of several designers at run-time – based on the user’s authorization. This post describes the steps needed to implement option (2) – because it’s a little tricky.

First, let’s assume we have a project in our solution called MyActivities. Let’s also assume that this project contains a custom activity called SendEmailActivity. This activity derives from CodeActivity and simply uses System.Net.Mail.SmtpClient to send an email within the Execute() method. Our SendEmailActivity activity has several InArguments – to allow the user to set the email address, subject, body, etc. The code for our SendEmailActivity might look like this:

1:using System;

2:using System.Activities;

3:using System.Net.Mail;

4:

5:namespace MyActivities

6: {

7:publicclass SendEmailActivity : CodeActivity

8: {

9:public InArgument<string> To { get; set; }

10:public InArgument<string> From { get; set; }

11:public InArgument<string> Subject { get; set; }

12:public InArgument<string> Body { get; set; }

13:public InArgument<string> Host { get; set; }

14:

15:protectedoverridevoid Execute(CodeActivityContext context)

16: {

17: SmtpClient client = new SmtpClient(Host.Get(context));

18:

19:try

20: {

21: client.Send(

22: From.Get(context),

23: To.Get(context),

24: Subject.Get(context),

25: Body.Get(context));

26: }

27:catch (Exception ex)

28: {

29:string error = ex.Message;

30:if (ex.InnerException != null)

31: {

32: error = ex.InnerException.Message;

33: }

34: Console.WriteLine("Failure sending email: " + error);

35: }

36: }

37: }

38: }

So now, to create an activity designer and associate it to the SendEmailActivity:

Create a Workflow Activity Designer Library project in the same solution with a name that appends ".VisualStudio.Design" to the name of the project where the custom activity resides. In this example, the name would be MyActivities.VisualStudio.Design

Create your activity designer. We'll call the designer class SendEmailActivityDesigner. (I’ve pasted the XAML for this designer at the end of this post)

From the new designer project (MyActivities.VisualStudio.Design), reference the following:

MyActivities - as a project reference

PresentationFramework

System.Activities.Core.Presentation

System.Activities.Presentation

In the code behind for the activity designer's XAML (SendEmailActivityDesigner.xaml.cs), implement the IRegisterMetadata interface. This includes utilizing Metadatastore in the IRegisterMetadata.Register() method. The code should look like this:

1:using System.Activities.Presentation.Metadata;

2:using System.ComponentModel;

3:

4:namespace MyActivities.VisualStudio.Design

5: {

6:publicpartialclass SendEmailActivityDesigner : IRegisterMetadata

7: {

8:public SendEmailActivityDesigner()

9: {

10: InitializeComponent();

11: }

12:

13:publicvoid Register()

14: {

15: AttributeTableBuilder builder = new AttributeTableBuilder();

16: builder.AddCustomAttributes(

17:typeof(SendEmailActivity),

18:new DesignerAttribute(typeof(SendEmailActivityDesigner)));

19: MetadataStore.AddAttributeTable(builder.CreateTable());

20: }

21: }

22: }

Now, in order for the VS activity designer to "see" your designer for the corresponding activity you need to make sure the MyActivities.VisualStudio.Design.dll file ends up in the same folder as MyActivities.dll. I've done this so far with a simple post-build event on the MyActivities.VisualStudio.Design project.

Then, finally, in the project that contains the workflow on which you want to drag-and-drop the SendEmailActivity make sure you add project references to both MyActivities and MyActivities.VisualStudio.Design.

* Note that this works only for the Visual Studio hosted workflow designer. If you re-host the designer in your own application you need to remove the "VisualStudio" part of the project/DLL name from your activity designer project. In our example this would be: MyActivities.Design.

Here’s the XAML code for the SendEmailActivityDesigner designer. The code-behind content is above, under step 4. (I’m certainly no WPF expert so go easy on me!)

Comments on this post: Associating a WF4 activity designer to a custom activity using MetadataStore

#re: Associating a WF4 activity designer to a custom activity using MetadataStore

Hi, Excellent article.Helped me a lot. I'm very new to workflow and started off with custom activities.they work absolutely fine. My next step is to associate a designer to it. Bit silly question, but the xaml was not generated but you had to write all the fields? :(Apologies if i'm sounding bit silly