共用方式為


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

Comments

  • Anonymous
    January 04, 2010
    Hi, just wanted to let you know that some of the code samples up there are looking a bit truncated to me on the right-hand side (IE8, screen res 1280x800) - Tim

  • Anonymous
    January 04, 2010
    Good stuff, man.  Keep it up!

  • Anonymous
    January 10, 2010
    Thank you Kushal. This is the post i've been waiting for.

  • Anonymous
    June 16, 2010
    hi. This works quite ok although its not very simple to implement. And there is another catch. What if you add an activity without designer (lets say Delay activity) That activity will not be changed in any way. You can easily try. ;) If you manage to find some solution to this I'll be very happy. :)

  • Anonymous
    August 16, 2010
    Hi, Could you tell me how I could implement a custom FlowSwitch? Thank you

  • Anonymous
    September 02, 2010
    sample is good, but too complicated to understand. "some of the code samples up there are looking a bit truncated to me on the right-hand side "-tim Could you fix it?

  • Anonymous
    June 10, 2011
    Is there a way to force the ModelItem by activity when showing the checkmark. I am seeing an issue where if you click a different activity the Check mark will be added to that activity instead because it is the primary selection.

  • Anonymous
    October 18, 2012
    Kushal, this of very great for us to get started on visual tracking. Only missing piece is applying adornment to FlowDecision it would be helpful if you could give us some pointers how to achieve this. We think it's not possible since FlowDecision is not been inherited from ActivityDesigner is that true?