The official Fatica Labs Blog! RSS 2.0
# Monday, March 14, 2011

There is an entire suite of command defined by the designer view:

      • DesignerView.CopyAsImageCommand;
      • DesignerView.CopyCommand;
      • DesignerView.CreateArgumentCommand;
      • DesignerView.CreateVariableCommand;
      • DesignerView.CreateWorkflowElementCommand;
      • DesignerView.CutCommand;
      • DesignerView.CycleThroughDesignerCommand;
      • DesignerView.DeleteBreakpointCommand;
      • DesignerView.DisableBreakpointCommand;
      • DesignerView.EnableBreakpointCommand;
      • DesignerView.ExpandAllCommand;
      • DesignerView.ExpandCommand;
      • DesignerView.ExpandInPlaceCommand;
      • DesignerView.FitToScreenCommand;
      • DesignerView.GoToParentCommand;
      • DesignerView.InsertBreakpointCommand;
      • DesignerView.PasteCommand;
      • DesignerView.RedoCommand;
      • DesignerView.ResetZoomCommand;
      • DesignerView.SaveAsImageCommand;
      • DesignerView.SelectAllCommand;
      • DesignerView.ToggleArgumentDesignerCommand;
      • DesignerView.ToggleImportsDesignerCommand;
      • DesignerView.ToggleMiniMapCommand;
      • DesignerView.ToggleSelectionCommand;
      • DesignerView.ToggleVariableDesignerCommand;
      • DesignerView.UndoCommand;
      • DesignerView.ZoomInCommand;
      • DesignerView.ZoomOutCommand;

But since the view is internal in the designer it is not automatic binding commands form the UI to the underlying target. So our hosting solution propose an attached property, to route the command to the view in a way suitable in pure markup too. The property we create is called DesignerCommandTarget, and is used as below:

   1:  <Button Style="{StaticResource toolButton}" ToolTip="Zoom In"   Command="wfview:DesignerView.ZoomInCommand"
   2:   host:HostingHelper.DesignerCommandTarget="{StaticResource wfHost}" 
   3:  >
   4:                      <Image Source="Assets/zoom_in.png"></Image>
   5:  </Button>
   6:                 

 

So we basically bind the command to the button by using Command, as usual, but we set the DesignerCommandTarget to our hosting instance, that is defined in the resource. In order to have the commands exposed by the designer in XAML, we added the wfview namespace reference as underlined below:

   1:  <Window x:Class="WF4Host.MainWindow"
   2:          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   3:          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:          xmlns:toolbox="clr-namespace:System.Activities.Presentation.Toolbox;assembly=System.Activities.Presentation"
   5:          xmlns:host="clr-namespace:WF4Host"
   6:          xmlns:custom="clr-namespace:MyActivities;assembly=MyActivities"
   7:          xmlns:wf="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
   8:          xmlns:wfview="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
   9:          xmlns:activities="clr-namespace:System.Activities.Statements;assembly=System.Activities"
  10:          Title="MainWindow" Height="650" Width="825"
  11:          Icon="Assets/App.ico"
  12:          TextOptions.TextFormattingMode="Display"
  13:         
  14:          >

Command routing is very simple, and it is shown below:

 

   1:   protected static void OnCommandTargetChanged(DependencyObject depo, DependencyPropertyChangedEventArgs depa)
   2:          {
   3:              var src = depo as ICommandSource;
   4:              if (null != src && depa.NewValue != null )
   5:              {
   6:                  var ctargetdescr = DependencyPropertyDescriptor.FromName("CommandTarget"
   7:                                                , depo.GetType()
   8:                                                , depo.GetType()
   9:                                                ,true);
  10:                  ctargetdescr.SetValue(depo
  11:  , (depa.NewValue as HostingHelper).Designer.Context.Services.GetService<DesignerView>());
  12:              }
  13:          }

Every time we attach the property we check if the target is a CommandSource, so basically the strategy works for any object implementing this interface. If this pre condition is satisfied, we simply bind the WorkflowDesigner view as a CommandTarget for that source. In this way commands from our UI behave as they are defined inside the workflow, and we don’t need to write any code behind to custom wire them.

Our example application now looks like this:

 

image

Code for this post is hosted here.
Monday, March 14, 2011 11:13:09 AM (GMT Standard Time, UTC+00:00)  #    Comments [0] - Trackback
Programmin | Recipes | ReHosting | WF4

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2014
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 123
This blog visits
All Content © 2014, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano