locked
Custom Activity Designer RRS feed

  • Question

  • Hello,

     

    I would like to know if the following is possible:

    We created a custom activity that is a container activity (derived from the SequenceActivity) which has already some child activities and bind activities in place. This activity is NOT a root activity (not derived from SequentialWorkflowActivity).

     

    [Designer(typeof(ActivityBaseDesigner))]

    public partial class ActivityBase : SequenceActivity

    {...}

     

    public class ActivityBaseDesigner : SequentialActivityDesigner

    {

       public override bool CanInsertActivities()

       {...}

    }

     

    We would like to use this activity as "base" activity for other custom activities (but not derive from it because of known issues when deriving from a custom activity). The ideea is to create each new custom activity as a SequenceActivity, drop the custom base activity into it as its only child and then drop some other activities (custom or not) into the base activity at predefined locations (in other words, we would like to restrict what kind of activities and where they are allowed to be put into the base container).

     

    public partial class NewCustomActivity : SequenceActivity

    {  ...

       private void InitializeComponent()

       {  ...

          this.activityBase1 = new ActivityBase(); // the only child

          this.Activities.Add(this.activityBase1);

          ...

       }

    }

     

    We would like to develop our new custom activities in the VS and also in an app rehosting the designer.

     

    Can we do this?

     

    We have already written a custom designer derived from the SequentialActivityDesigner for our base container, overwritten the CanInsertActivities method, and played around a bit with the activity in VS, but nothing happens when:

     

    - We're attempting to change the base container itself in the VS (this was just to test if we can pop child activities at unallowed locations). Can it be that custom activity designers aren't supported when designing the activity itself ? 

     

    - The base container is locked when put in another custom activity. Setting the CanModifyActivities property of the base container on true at the end of the InitializeComponent() causes a compiler error. How can we unlock the base container?

     


    Thanks.

    Aleydis

    Wednesday, November 7, 2007 11:57 AM

Answers

  • What you can do is add a virtual method "AddDefaultChildren", and override (while calling base.AddDefaultChildren) in inherited classes.

    In your designer, override InitializeComponent, and do in inspection (like if activity.HasAddedDefaulChildren, then) and call the AddDefaultChildren method.


    Then you can get the behavior you want.  Note though you will also have to implement a markup serializer as well if you want these activities to NOT get serialized, but it looks like you are looking for a templating behavior for which this approach would be OK.

    Thursday, November 8, 2007 4:35 PM

All replies

  • When you build a composite activity with children you are not able to add additional children when the activity is used, you can not unlock ActivityBase.  Once option is to instead create a custom toolboxitem for your base activity.  This would cause the activity to be composed when it is dragged from the toolbox.  Take a look at the post at http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=723276&SiteID=1 for an example of a custom StateActivity.

    Wednesday, November 7, 2007 4:12 PM
  • Hi Tom,

     

    I already saw that post (and some others as well, like

    http://blogs.msdn.com/sergeychub/archive/2006/07/19/672179.aspx.

    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2035518&SiteID=1)

     

    When I'm developing new stuff I have practically only three choices:

    (1) inheritance, (2) containment and (3) code replication.

     

    In my particular case I'm keen on (1) because I think it will suit me best. Using ToolboxItems seems to me something like a template for (3) but I guess I have no alternative for the time being.

     

    Do you know if any chance in the future release(s) to be able to add children when deriving from an activity but not being allowed to mess around (move/delete) with the "inherited" children? After all, some standard .NET composite activities allow the adding of children after the composite activity was designed (for instance, when designing the parent workflow).

     

    Just another question: I don't think I quite understood how the associated designer for an activity is supposed to work.

    Is it by design that the ActivityDesigner won't step in when the activity itself is being designed/changed? 

    Does it step in only when the workflow (i.e. root activity) containing said activity is being designed?  

     

    Thanks again,

    Aleydis

     

     

    Thursday, November 8, 2007 7:33 AM
  • What you can do is add a virtual method "AddDefaultChildren", and override (while calling base.AddDefaultChildren) in inherited classes.

    In your designer, override InitializeComponent, and do in inspection (like if activity.HasAddedDefaulChildren, then) and call the AddDefaultChildren method.


    Then you can get the behavior you want.  Note though you will also have to implement a markup serializer as well if you want these activities to NOT get serialized, but it looks like you are looking for a templating behavior for which this approach would be OK.

    Thursday, November 8, 2007 4:35 PM
  •  

    I've tried the two approaches suggested by Tom and Jonathan, respectively.

     

    Tom's approach works as expected - I get a new derived activity which I can see in the designer with all the children it contains and have no restrictions whatsoever in changing it because it's basically code replication (all the children get generated in the designer.cs file of the new activity).

     

    Jonathan's approach has some unexpected side effects.

    My base activity contains an EventHandlingScopeActivity as top child activity (including all the stuff such an activity usually contains: EventHandlersActivity , etc). The derived activity doesn't show anything when opened for changes in the VS designer (it's apparently empty), which I expected somewhat. But it also doesn't show anything when used in a workflow, which was unexpected. I figured out that my custom designer associated to the base activity had the ContainedDesigners null or empty. I instantiated via reflection an EventHandlingScopeDesigner (internal designer for the EventHandlingScopeActivity) and after that I could see the content of my derived activity when used in a workflow but it wasn't locked as it usually is. 

     

    My questions are:

    - Is there anything I can do so my derived activity will be locked when displayed inside as workflow?

    - Is it by design that the associated ActivityDesigner of a custom (derived) activity won't be invoked when designing the activity itself? Because if it is so I can add new children to the activity only through code since the designer doesn't show me any of the existing/inherited children.

     

    Friday, November 9, 2007 2:04 PM