Validating wich activities I can insert on my custom activity.
Hi.
I have a custom composite activity, and I don't want that an activity of the same type is inserted as child of it, in any level.
I don't have problems when I want to insert the same type activity as a direct child, because I can override the CanInsertActivities on the my designer.
But if I add a composite activity, I cannot find out how can I forbid to add an activity of the parent type inside it....
(Like a similar behaviour when adding a transactionscope that is indirectly a child of another transactionscope, but instead of showing the validator, I don't want the user to be allowed to add it...)
Thanks in advance,
Matias
[686 byte] By [
Matt] at [2007-12-25]
Matt,
I don't think you can do this 100% with the designers. As far as I know, there's no way to get notifications in the parent designer that a grandchild (at any arbitrary level) is getting inserted into the tree, so an activity validator would certainly be needed.
However, you can certainly have your activity designer prevent some common scenarios that would help the user:
1- You can prevent the user from adding a direct child of the same type
2- You can prevent the user from copy-pasting/dragging a direct composite activity child that contains an activity of the same as a direct/indirect child (i.e. you can prevent the user from dragging a sequence activity containing one of your activities into your activity).
3- You can prevent an instance of your activity being added anywhere there's an activity of the same type as a parent/grandparent.
Here's some sample code to do just that:
public class ParentActivityDesigner : SequenceDesigner
{
/// <summary>
/// Verify that the activities
/// being inserted are not and don't contain
/// a ParentActivity as a child.
/// </summary>
/// <param name="insertLocation"></param>
/// <param name="activitiesToInsert"></param>
/// <returns></returns>
public override bool CanInsertActivities(HitTestInfo insertLocation,
System.Collections.ObjectModel.ReadOnlyCollection<Activity> activitiesToInsert)
{
bool canDo = base.CanInsertActivities(insertLocation, activitiesToInsert);
bool contains = ContainsParentActivity(activitiesToInsert);
return canDo && !contains;
}
private bool ContainsParentActivity(IEnumerable<Activity> activities)
{
bool found = false;
foreach ( Activity act in activities )
{
if ( act is ParentActivity )
found = true;
else
{
CompositeActivity composite = act as CompositeActivity;
if ( composite != null )
{
found = ContainsParentActivity(composite.Activities);
}
}
if ( found )
return true;
}
return false;
}
/// <summary>
/// Verify that in the parent chain where
/// we are going to be inserted there isn't any
/// other ParentActivity
/// </summary>
/// <param name="parentActivityDesigner"></param>
/// <returns></returns>
public override bool CanBeParentedTo(CompositeActivityDesigner parentActivityDesigner)
{
bool canDo = base.CanBeParentedTo(parentActivityDesigner);
Activity parent = parentActivityDesigner.Activity;
while ( parent != null )
{
if ( parent is ParentActivity )
return false;
parent = parent.Parent;
}
return canDo;
}
}This does break in one scenario, and that's when dragging a container activity (such as a sequence activity) that contains a ParentActivity into a sequence activity within a ParentActivity (man, that's confusing!).
It might be a good starting point, though.