Windows Workflow 4 Designer WPF Application

One of the coolest things about Windows Workflow Foundation is the workflow designer. It’s visual programming.  You drag and drop your components onto the design surface and configure the properties of each module to create a functional application. Microsoft makes it easy to re-host the workflow designer in your own applications, providing you with an easy way to include customization and configuration tools for your workflows.

I found a great bare-bones tutorial at MSDNRehosting the Workflow Designer.

There’s some important functionality missing from this tutorial, though. There are no mechanisms for opening or saving workflow files, and the toolbox is only populated with two controls. So, I’ve taken the MSDN tutorial, compressed the steps, and added some additional key functionality.

  1. Create a new WPF Application. I called mine “WorkflowEditor.”
  2. Add references
    • System.Activities
    • System.Activities.Core.Presentation
    • System.Activities.Presentation
  3. Copy/paste the XAML below into MainWindow.xaml
  4. Copy/paste the code-behind below into MainWindow.xaml.cs

That’s it! Once you’re this far, you should be able to run the program. If you’re looking for a more in-depth, step-by-step explanation of the code, follow the link above to the MSDN tutorial. The only differences below are that I added some reflection code to extract the “standard” workflow activities, and I added Open and Save buttons.

<Window x:Class="adamprescott.net.WorkflowEditor.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="500" Width="800">
    <Grid Name="grid1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition Width="4*" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="36" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <ToolBar Grid.Row="0" Grid.ColumnSpan="3">
            <Button Click="OnOpenClick">Load</Button>
            <Button Click="OnSaveClick">Save</Button>
        </ToolBar>
    </Grid>
</Window>
using System;
using System.Activities;
using System.Activities.Core.Presentation;
using System.Activities.Presentation;
using System.Activities.Presentation.Toolbox;
using System.Activities.Statements;
using System.Linq;
using System.Reflection;
using System.Windows.Controls;
using Microsoft.Win32;

namespace adamprescott.net.WorkflowEditor
{
    public partial class MainWindow
    {
        private WorkflowDesigner _designer;

        public MainWindow()
        {
            InitializeComponent();
            RegisterMetadata();
            InitializeDesigner();
            AddToolBox();
        }

        private void AddDesigner()
        {
            _designer = new WorkflowDesigner();
            Grid.SetColumn(_designer.View, 1);
            Grid.SetRow(_designer.View, 1);
            grid1.Children.Add(_designer.View);
        }

        private void RegisterMetadata()
        {
            var dm = new DesignerMetadata();
            dm.Register();
        }

        private ToolboxControl GetToolboxControl()
        {
            var toolbox = new ToolboxControl();
            PopulateToolboxCategoryFromAssembly(toolbox, typeof(Assign).Assembly, "Standard");
            return toolbox;
        }

        private void PopulateToolboxCategoryFromAssembly(ToolboxControl toolbox, Assembly assembly, string categoryName)
        {
            var tools = assembly.GetTypes()
                .Where(t => t.IsSubclassOf(typeof(Activity))
                    && t.IsPublic
                    && !t.IsAbstract
                    && HasParameterlessContructor(t))
                .Select(t => new ToolboxItemWrapper(t.FullName, t.Assembly.FullName, null, t.Name))
                .OrderBy(t => t.DisplayName);

            var category = new ToolboxCategory(categoryName);
            foreach (var t in tools)
            {
                category.Add(t);
            }
            toolbox.Categories.Add(category);
        }

        private bool HasParameterlessContructor(Type t)
        {
            var ctors = t.GetConstructors();
            var parameterless = ctors.Where(c => c.GetParameters().Count() == 0)
                .FirstOrDefault();
            return parameterless != null;
        }

        private void AddToolBox()
        {
            var tc = GetToolboxControl();
            Grid.SetColumn(tc, 0);
            Grid.SetRow(tc, 1);
            grid1.Children.Add(tc);
        }

        private void AddPropertyInspector()
        {
            Grid.SetColumn(_designer.PropertyInspectorView, 2);
            Grid.SetRow(_designer.PropertyInspectorView, 1);
            grid1.Children.Add(_designer.PropertyInspectorView);
        }

        private void OnOpenClick(object sender, System.Windows.RoutedEventArgs e)
        {
            var dlg = new OpenFileDialog();
            if (dlg.ShowDialog().Value)
            {
                InitializeDesigner();
                _designer.Load(dlg.FileName);
            }
        }

        private void OnSaveClick(object sender, System.Windows.RoutedEventArgs e)
        {
            var dlg = new SaveFileDialog();
            if (dlg.ShowDialog().Value)
            {
                _designer.Save(dlg.FileName);
            }
        }

        private void InitializeDesigner()
        {
            AddDesigner();
            AddPropertyInspector();
        }
    }
}
Advertisements

2 thoughts on “Windows Workflow 4 Designer WPF Application”

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s