If you're creating a custom composite activity, you might need to restrict whether a given activity can be inserted as a child at a specific point of your composite activity when working on the Workflow Designer. Fortunately, this is actually fairly easy using the designer facilities in Windows Workflow Foundation. Let's quickly sample this by building a custom CodeFirstSequentialActivity, which is a simple sequential composite activity that requires that the first child activity in the sequence is a CodeActivity. Other than that, any other type of activity can be a child. First, we'll create a custom designer class for our activity, which we'll inherit from the SequenceDesigner class. In it, we'll override the CanInsertActivities method, in which we'll do a simple test: If the insertion point is the first one on our composite activities, then we'll check that the first activity being dropped/inserted is indeed a CodeFirstActivity, and, if so, just return false to block the designer from inserting the child activities: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } public class CodeFirstSequentialActivityDesigner : SequenceDesigner { public override bool CanInsertActivities(HitTestInfo insertLocation, System.Collections.ObjectModel.ReadOnlyCollection<Activity> activitiesToInsert) { bool canDo = base .CanInsertActivities(insertLocation, activitiesToInsert); CompositeActivity theActivity = Activity as CompositeActivity; if ( theActivity != null ) { // first activity in can only be a CodeActivity if ( insertLocation.MapToIndex() == 0 ) { if ( !(activitiesToInsert[0] is CodeActivity) ) { return false ; } } } return canDo; } } Then, it's just a matter of associating our custom designer with our activity: .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } [Designer( typeof (CodeFirstSequentialActivityDesigner))]
Read More...