In order to reach the context of an Assign activity, i hosted it into a custom activity like follows :
<sap:ActivityDesigner x:Class="ARIASquibLibrary.Design.CustomAsignDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:statements="http://schemas.microsoft.com/netfx/2009/xaml/activities" Collapsible="False">
<sap:ActivityDesigner.Template>
<ControlTemplate TargetType="sap:ActivityDesigner">
<Grid>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</sap:ActivityDesigner.Template>
<DockPanel LastChildFill="True">
<sap:WorkflowItemPresenter Item="{Binding Path=ModelItem.Body, Mode=TwoWay}"/>
</DockPanel>
And the code from the library:
public sealed class CustomAssign : NativeActivity, IActivityTemplateFactory
{
[Browsable(false)]
public Activity Body { get; set; }
protected override void Execute(NativeActivityContext context)
{
ActivityInstance res = context.ScheduleActivity(Body, new CompletionCallback(OnExecuteComplete));
}
/// <summary>
/// Called from Execute when Condition evaluates to true.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="instance">The instance.</param>
public void OnExecuteComplete(NativeActivityContext context, ActivityInstance instance)
{
//to be added
}
Activity IActivityTemplateFactory.Create(System.Windows.DependencyObject target)
{
return new CustomAssign
{
Body = new Assign()
};
}
}
When dragging this activity on the designer, it looks exactly as the default Assign. But the issue appears when trying to delete it. Being hosted, its parent will remain on the designer because, in fact, i delete the body even if the user doesn't see this.
Is there a way to propagate to the parent in order to delete the entire activity from the designer?
Ok so you will need to override the OnModelChanged event on your workflow designer.
ModelService modelSvc = (ModelService)designer.Context.Services.GetService<System.Activities.Presentation.Services.ModelService>();
if (modelSvc != null)
{
modelSvc.ModelChanged += OnModelChanged;
}
Once you have done this you can access the activities that have been removed from the designer.
void modelSvc_ModelChanged(object sender, ModelChangedEventArgs e)
{
//we have deleted something from the design surfaace
if (e.ModelChangeInfo.ModelChangeType == ModelChangeType.CollectionItemRemoved)
{
ModelItem modelItem = (ModelItem)e.ModelChangeInfo.Value;
}
}
Based on the model item from the deleted activity you can then traverse the workflow tree to find the relevant activities you wish to remove.
This concept is explained very well here.
You can then remove activities using a ModelEditingScope with the following code.
using (ModelEditingScope editingScope = modelSvc.Root.BeginEdit("Activities"))
{
//to add an activity
modelSvc.Root.Properties["Activities"].Collection.Add(new Sequence());
//to remove an activity
modelSvc.Root.Properties["Activities"].Collection.Remove(*A model Item to remove);
editingScope.Complete();
}
This is not a trivial task and there are a few funnies when doing this. Personally I have not implemented this exact requirement in my own applications, but I have done similar deletion of variables associated to the deleted activity and there are various gotchas but the above code should give you a starting point.