Thursday, November 22, 2012

Hosted Designer


What if we wanted to create a custom activity like the PrePostSequence and have someone else who does not have Visual Studio use it? Many products allow end users to customize workflows. Windows Workflow Foundation 4 allows us to host the designer in an application quite easily. In this article, we will host the designer and use your custom activity.
  1. Start Microsoft Visual Studio 2010 from Start | All Programs | Microsoft Visual Studio 2010.
  2. To begin this project we can use the solution we finished from the previous article Activity Designers
  3. In the Solution Explorer, right click on the HelloWorkflow solution and select Add / New Project.
  4. From the Windows templates Add new WPF Application named HelloDesigner.
  5. Set the HelloDesigner project as the Startup project. To do this, in the Solution Explorer, right click on the HelloDesigner project and point to Set as Startup Project.
  6. In the Solution Explorer, right-click on the HelloDesigner project and point to Add references. Choose the following assemblies from the .Net tab
    1. System.Activities.Presentation
    2. 
    System.Activities.Core.Presentation
    3. 
    System.Activities
  7. From the Projects tab, add the following assemblies:
    1. 
    HelloWorkflow.Activities
    2. 
    HelloWorkflow.Activities.Designers
  8. Open MainWindow.xaml and modify it as shown
    XAML (C#)
    <Window x:Class="HelloDesigner.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="600" Width="1000">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="4*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid Name="grid1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="4*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
            </Grid>
            <TextBox Grid.Row="1" Name="textXAML"
                     VerticalScrollBarVisibility
    ="Visible" />
        </Grid>
    </Window>

    XAML (VB)
    <Window x:Class="MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="600" Width="1000">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="4*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Grid Name="grid1">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="4*" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>
            </Grid>
            <TextBox Grid.Row="1" Name="textXAML"
                     VerticalScrollBarVisibility="Visible" />
        </Grid>
    </Window>

  9. Open MainWindow.xaml.cs (C#) or MainWindow.xaml.vb, to do this, right-click the MainWindow.xaml file and choose View Code (F7).
  10. Add the following namespace directives:
    C#
    using System.Activities.Presentation;
    using System.Activities.Statements;
    using System.Activities.Presentation.Toolbox;
    using System.Activities.Core.Presentation;
    using System.Activities.Presentation.Metadata;
    using System.ComponentModel;
    using HelloWorkflow.Activities;
    using HelloWorkflow.Activities.Designers;
    Visual Basic
    Imports System.Activities.Presentation
    Imports System.Activities.Statements
    Imports System.Activities.Presentation.Toolbox
    Imports System.Activities.Core.Presentation
    Imports System.Activities.Presentation.Metadata
    Imports System.ComponentModel
    Imports HelloWorkflow.Activities
    Imports HelloWorkflow.Activities.Designers
  11. Add a field of type WorkflowDesigner:
    C#
    WorkflowDesigner workflowDesigner = new WorkflowDesigner();

    Visual Basic
    Private workflowDesigner As WorkflowDesigner = New WorkflowDesigner()

  12. Create a new function named RegisterMetadata as shown:
    C#
    private void RegisterMetadata()
    {
        DesignerMetadata metaData = new DesignerMetadata();
        metaData.Register();
        AttributeTableBuilder builder = new AttributeTableBuilder();
        MetadataStore.AddAttributeTable(builder.CreateTable());
    }
    Visual Basic
    Public Sub RegisterMetadata()
        Dim metaData As DesignerMetadata = New DesignerMetadata()
        metaData.Register()
        Dim builder As AttributeTableBuilder = New AttributeTableBuilder()
        MetadataStore.AddAttributeTable(builder.CreateTable())
    End Sub
     Note : This function enables the designer metadata store
    When you host the designer you can control the toolbox. You choose what controls will appear, the categories that will appear in, and even the names of the controls.
  13. Add a function named CreateToolboxControl, which will create and populate the toolbox with four items:
    C#
    private ToolboxControl CreateToolboxControl()
    {
        //Create the ToolBoxControl
        ToolboxControl ctrl = new ToolboxControl();

        //Create a collection of category items
        ToolboxCategory category = new ToolboxCategory("Hello Workflow");

        //Creating toolboxItems
        ToolboxItemWrapper tool0 = new ToolboxItemWrapper(
            "System.Activities.Statements.Assign",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
            , null,
            "Assign");
        ToolboxItemWrapper tool1 = new ToolboxItemWrapper(
            "System.Activities.Statements.Sequence",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
            null,
            "Sequence");
        ToolboxItemWrapper tool2 = new ToolboxItemWrapper(
            "System.Activities.Statements.TryCatch",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
            null,
            "Try It"); // Can use a different name
        ToolboxItemWrapper tool3 = new ToolboxItemWrapper(
            "HelloWorkflow.Activities.PrePostSequence",
            "HelloWorkflow.Activities",
            null,
            "PrePostSequence");

        //Adding the toolboxItems to the category.
        category.Add(tool0);
        category.Add(tool1);
        category.Add(tool2);
        category.Add(tool3);

        //Adding the category to the ToolBox control.
        ctrl.Categories.Add(category);
        return ctrl;
    }

    Visual Basic
    Private Function CreateToolboxControl() As ToolboxControl
        'Create the ToolBoxControl
        Dim ctrl As ToolboxControl = New ToolboxControl()

        'Create a collection of category items
        Dim category As ToolboxCategory = New ToolboxCategory("Hello Workflow")

        'Creating toolboxItems
        Dim tool0 As ToolboxItemWrapper = New ToolboxItemWrapper(
            "System.Activities.Statements.Assign",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
            Nothing,
            "Assign")
        Dim tool1 As ToolboxItemWrapper = New ToolboxItemWrapper(
            "System.Activities.Statements.Sequence",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
            Nothing,
            "Sequence")
        Dim tool2 As ToolboxItemWrapper = New ToolboxItemWrapper(
            "System.Activities.Statements.TryCatch",
            "System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35",
            Nothing,
            "Try It") ' Can use a different name
        Dim tool3 As ToolboxItemWrapper = New ToolboxItemWrapper(
            "HelloWorkflow.Activities.PrePostSequence",
            "HelloWorkflow.Activities",
            Nothing,
            "PrePostSequence")

        'Adding the toolboxItems to the category.
        category.Add(tool0)
        category.Add(tool1)
        category.Add(tool2)
        category.Add(tool3)

        'Adding the category to the ToolBox control.
        ctrl.Categories.Add(category)
        Return ctrl
    End Function

  14. Add a function named AddDesigner which will add the designer to your window:
    C#
    private void AddDesigner()
    {
        //Create an instance of WorkflowDesigner class
        this.workflowDesigner = new WorkflowDesigner();

        //Place the WorkflowDesigner in the middle column of the grid
        Grid.SetColumn(this.workflowDesigner.View, 1);

        // Flush the workflow when the model changes
        workflowDesigner.ModelChanged += (s, e) =>
        {
            workflowDesigner.Flush();
            textXAML.Text = workflowDesigner.Text;
        };

        //Load a new Sequence as default.
        this.workflowDesigner.Load(new Sequence());

        //Add the WorkflowDesigner to the grid
        grid1.Children.Add(this.workflowDesigner.View);

        // Add the Property Inspector
        Grid.SetColumn(workflowDesigner.PropertyInspectorView, 2);
        grid1.Children.Add(workflowDesigner.PropertyInspectorView);

        // Add the toolbox
        ToolboxControl tc = CreateToolboxControl();
        Grid.SetColumn(tc, 0);
        grid1.Children.Add(tc);
    }
    Visual Basic
    Private Sub AddDesigner()

        'Create an instance of WorkflowDesigner class
        workflowDesigner = New WorkflowDesigner()

        'Place the WorkflowDesigner in the middle column of the grid
        Grid.SetColumn(workflowDesigner.View, 1)

        ' Setup the Model Changed event handler
        AddHandler workflowDesigner.ModelChanged,
            Function(sender As Object, e As System.EventArgs)
                ' Flush the workflow when the model changes
                workflowDesigner.Flush()
                textXAML.Text = workflowDesigner.Text
                Return Nothing
            End Function

        'Load a new Sequence as default.
        workflowDesigner.Load(New Sequence())

        'Add the WorkflowDesigner to the grid
        grid1.Children.Add(workflowDesigner.View)

        ' Add the Property Inspector
        Grid.SetColumn(workflowDesigner.PropertyInspectorView, 2)
        grid1.Children.Add(workflowDesigner.PropertyInspectorView)

        ' Add the toolbox
        Dim tc As ToolboxControl = CreateToolboxControl()
        Grid.SetColumn(tc, 0)
        grid1.Children.Add(tc)
    End Sub
  15. Modify MainWindow’s constructor to call the functions you have just added:
    C#
    public MainWindow()
    {
        InitializeComponent();
        RegisterMetadata();
        AddDesigner();
    }
    Visual Basic
    Public Sub New()
        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        RegisterMetadata()
        AddDesigner()
    End Sub
  16. Ensure that HelloDesigner is set as the startup project.
  17. Press F5 to launch the application in debug mode.
  18. When the design window appears drop a PrePostSequence on the designer surface.
  19. You should see the following:
    The HelloDesigner application hosting the WorkflowDesigner
    The HelloDesigner application hosting the WorkflowDesigner



3 comments:

  1. Hi,
    how can I have your blog template ?

    ReplyDelete
    Replies
    1. I don't use template, I just design by blogger tools

      Delete
  2. Hi friend. why don't you cooperate with me, since the cooperation has no harm but benefit to both. just put a link on your blog and I will put yours in my blog.Why you do not agree? a link in facebook can take how many readers for you? I have blog also, but I gave up popularizing it in facebook. this is my blog: excelcsharp.blog.com. I think you can think about it.Please reply me!Thanks!

    ReplyDelete

YallaTech Facebook page