Base Designer with additional adornments

In the previous two posts, we talked about the visual view on the Workflow tracking data and how we can have a restricted debugging experience in the re-hosted scenarios.

Moving forward, the next question I get from customers  - Is there a way I can show some kind of adorner on the designer when it executes a specific activity in addition to the debug adornment? Also, I want these adornments universal for Out of Box as well as Custom Activities. The adorner can be as simple as a check mark saying the activity executed.

Lets take a look into how we can achieve that?

All the Workflow activity designers directly or indirectly derive from “ActivityDesigner”. Hence in our Re-hosted application, in App.Xaml.cs, we say:

 protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);

    Style activityDesignerStyle = (Style)Resources[typeof(ActivityDesigner)];
    
    foreach (Type activityDesignerType in typeof(System.Activities.Core.Presentation.DesignerMetadata).Assembly.GetTypes())
    {
         if (typeof(ActivityDesigner).IsAssignableFrom(activityDesignerType))
        {
              Resources[activityDesignerType] = activityDesignerStyle;
         }
     }
}

The App.Xaml contains:

  <Application.Resources>  
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="CustomWorkflowElementDesignerTemplate.xaml" />     
            </ResourceDictionary.MergedDictionaries>
            <Style TargetType="{x:Type swd:ActivityDesigner}">
                <Setter Property="Template" Value="{StaticResource WorkflowElementDesignerDefaultTemplate}" />
            </Style>
        </ResourceDictionary>        
 </Application.Resources>

The CustomWorkflowElementDesignerTemplate.Xaml is where we have provided the additional adornments in our Base Designer. Up till now, classic WPF. Essentially saying, that for all UI controls which directly or indirectly derive from “ActivityDesigner”, please use the above styling.

The above approach is however static. The additional adornments will appear always. However, we want to go one step ahead. We want the adornments to appear only when the activity has executed. For that, we will take the help of the Model attached properties.

 //Attached Properties for the glyphs/tooltip on the designers 
AttachedProperty<Visibility> attachProp = null; 
AttachedProperty<Visibility> attachPropTipShow = null; 
AttachedProperty<string> attachPropTip = null;

The ‘attachProp’ is for the check mark adornment. The other two to ensure that we can have Tooltips whose content changes once the activity has executed.

The declaration of the attached properties continues as:

 //Attached Property to decide when to show the glyphs as the activity finishes execution
attachProp = new AttachedProperty<Visibility>()
{
        Name = "Show",
        Getter = (modelItem) => ShowExecute.IsExist(modelItem),
        Setter = (modelItem, show) => ShowExecute.Add(modelItem),
        OwnerType = typeof(Activity)

 };

Where “ShowExecute”, is an helper class which knows which model items have completed execution so as to turn on the flag for the check mark to be shown. The flag is used in Xaml as follows:

 <Viewbox x:Uid="checkBox" Grid.Row="0" Margin="3,0,3,0" Width="16" Height="16" 
                 Visibility="{Binding Path=ModelItem.Show, RelativeSource={RelativeSource AncestorType={x:Type swd:WorkflowViewElement}}}" 
                 IsHitTestVisible="False" HorizontalAlignment="Left">
             <Rectangle x:Uid="Rectangle_check" Width="16" Height="16" >
                <Rectangle.Fill>
                       <ImageBrush ImageSource="4918842_low.jpg" />
                 </Rectangle.Fill>    
              </Rectangle>
</Viewbox>

“4918842.jpg” is the beautiful check mark we will show on the designer.

Finally, we register the attached properties into the WorkflowDesigner’s attached property services as follows:

 //Adding the attached properties to the designer.
this.WorkflowDesigner.Context.Services.GetService<AttachedPropertiesService>().AddProperty(attachProp);
this.WorkflowDesigner.Context.Services.GetService<AttachedPropertiesService>().AddProperty(attachPropTipShow);
this.WorkflowDesigner.Context.Services.GetService<AttachedPropertiesService>().AddProperty(attachPropTip);

Finally, in our ShowDebug method, when we know that a specific activity has executed, we can turn on the flag to display the check mark through the attached property:

 dynamic mi = this.WorkflowDesigner.Context.Items.GetValue<Selection>().PrimarySelection;
mi.Show = Visibility.Visible ;
attachProp.NotifyPropertyChanged((ModelItem)mi);

Please note that the usage of the dynamic word here to use the access the model item attached properties, is available only through the post B2 bits(if you have access to SLCTP). Otherwise, you would have to use the B2(a bit tedious route) as follows:

TypeDescriptor.GetProperties(mi)["Show"].SetValue(mi, Visibility.Visible);

I have also attached the zip with the entire source code.

In addition to the above change for the dynamic keyword usage, one additional change if you are working with B2 bits:

Replace:

 <swd:CachedResourceDictionaryExtension x:Uid="ResourceDictionary_4" 
                Source="/System.Activities.Presentation;component/System/Activities/Presentation/ColorResources.xaml"/>

to

 <swd:CachedResourceDictionaryExtension x:Uid="ResourceDictionary_4" 
                Source="/System.Activities.Presentation;component/System/WorkflowModel/Design/ColorResources.xaml"/>

With this, now in a re-hosted application, you get the following custom adornment and Tooltip when visualizing the tracking data:

image

The above approach can be used not only in the case of VisualWorkflowTracking, but also more generally where users want additional UI on top of their activity designers including the Out of Box activities.

Hope this helps!

Thanks,

Kushal.

VisualTrackingWithStepService.zip