The official Fatica Labs Blog! RSS 2.0
# Saturday, March 05, 2011

This post is based on this great post from The Problem Solver, but here we try to use less code behind and more markup language, to let the “host” decide where to put the designer components in his application. Basically there is three main chunk involved in hosting the WF:

  1. The main designer surface
  2. The property view
  3. The toolbox.

Components 1) and 2) are exposed as property of the WorkflowDesigner class, that itself is not a UIElement, but a simple class derived from object. The two property of interest are View and PropertyInspectorView, and both are UIElements. The problem is: how to let’s the host application writer to decide where to place these in XAML ? Lets start creating a class that act as an helper, and provide inside it some initialization code:

namespace WF4Host
    public class HostingHelper:DependencyObject
        public WorkflowDesigner Designer { get { return workflowDesigner;} }
        WorkflowDesigner workflowDesigner;
        public HostingHelper()
            workflowDesigner = new WorkflowDesigner();
            new DesignerMetadata().Register();
            //Creates an empty workflow
            workflowDesigner.Load(new Sequence());

basically we creates an instance of the WorkflowDesigner itself, load a first Sequence activity, and start the designer runtime. In xaml we can declare such an object as a StaticResource:

   1:  <Window x:Class="WF4Host.MainWindow"
   2:          xmlns=""
   3:          xmlns:x=""
   4:          xmlns:host="clr-namespace:WF4Host"
   5:          xmlns:wf="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
   6:          Title="MainWindow" Height="650" Width="825"
   7:          >
   8:      <Window.Resources>
   9:          <host:HostingHelper x:Key="wfHost"/>
  10:          <LinearGradientBrush x:Key="backBrush" StartPoint="0,0" EndPoint="0,1" >
  11:              <GradientStop Offset="0.1" Color="DarkSlateBlue"></GradientStop>
  12:              <GradientStop Offset="0.2" Color="DarkSlateGray"/>
  13:              <GradientStop Offset="0.9" Color="BlanchedAlmond"/>
  14:          </LinearGradientBrush>
  15:      </Window.Resources>


Easy: at line 4 we add the namespace for our project. At line 9 we declare an instance of our HostingHelper and we name it wfHost. Remaining resources are just some beautiful ( ehm ) arts.

Then we need to present the graphical components. Lets declare in our code a control deriving from grid:

   1:  namespace WF4Host
   2:  {
   3:      public class MainViewPresenter : Grid
   4:      {
   5:          public HostingHelper HostingHelper
   6:          {
   7:              get { return (HostingHelper)GetValue(HostingHelperProperty); }
   8:              set { SetValue(HostingHelperProperty, value); }
   9:          }
  11:          public static readonly DependencyProperty HostingHelperProperty =
  12:              DependencyProperty.Register("HostingHelper", typeof(HostingHelper)
  13:              , typeof(MainViewPresenter)
  14:              , new UIPropertyMetadata(null, new PropertyChangedCallback(OnHostingHelperChanged)));
  16:          protected static void OnHostingHelperChanged(DependencyObject dobj
  17:              , DependencyPropertyChangedEventArgs dpcea)
  18:          {
  19:              if (dobj is MainViewPresenter)
  20:              {
  21:                  var mvp = dobj as MainViewPresenter;
  22:                  mvp.Children.Clear();
  23:                  if (dpcea.NewValue != null)
  24:                  {
  25:                      var host = dpcea.NewValue as HostingHelper;
  26:                      host.Designer.View.SetValue(Panel.HorizontalAlignmentProperty, HorizontalAlignment.Stretch);
  27:                      host.Designer.View.SetValue(Panel.VerticalAlignmentProperty, VerticalAlignment.Stretch);
  28:                      mvp.Children.Add(host.Designer.View);
  29:                  }
  30:              }
  31:          }
  32:      }
  33:  }


So this class is the MainView presenter. We call the Main View the one in which the WF is actually drawn. This control has a dependency property called HostingHelper, so we can bind it to the current HostingHelper that orchestrates the Workflow design. Let see how to do it in xaml:

   1:  <Grid Name="grid">
   2:              <Grid.RowDefinitions>
   3:                  <RowDefinition Height="32"/>
   4:                  <RowDefinition Height="*"/>
   5:              </Grid.RowDefinitions>
   6:                  <Grid.ColumnDefinitions>
   7:              <ColumnDefinition Width="100"></ColumnDefinition>
   8:              <ColumnDefinition></ColumnDefinition>
   9:              <ColumnDefinition Width="100"></ColumnDefinition>
  10:          </Grid.ColumnDefinitions>
  12:              <host:MainViewPresenter
  13:               HostingHelper="{StaticResource wfHost}"  Grid.Column="1" Grid.Row="1"/>
  15:          </Grid>

So at line 12 we declare our presenter, and we bind his hosting helper property to the hosting helper instance wfHost.

This is the current result:


So we achieved less code behind and more “blendability” by creating a little tool library. We should improve it with others components to complete the designer environment. I decided to publish this example as a project on codeplex, so you can join to use and improve it.

Saturday, March 05, 2011 10:49:00 AM (GMT Standard Time, UTC+00:00)  #    Comments [2] - Trackback
Programmin | Recipes | ReHosting | WF4

My Stack Overflow

Send mail to the author(s) E-mail

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

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

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