[WF4]Create A Custom Activity

One of the great feature of WF4 is that we can create our own Activity (and its surface) very easy. For example, let's create a PersonInfoActivity:
You will see this in workflow:


But, can we make it more interesting? Say, let it looks like this:

To do this: we need to create an Activity Designer, which is actually a WPF xaml file.

<sap:ActivityDesigner x:Class="MyActivityDesignerLibrary.PersonInfoActivityDesigner"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"

    xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"

    xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation"

    xmlns:s="clr-namespace:System;assembly=mscorlib"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" >

    <sap:ActivityDesigner.Resources>

        <!--<ResourceDictionary>

            <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter"/>

        </ResourceDictionary>-->

        <sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter"/>

        <DataTemplate x:Key="Collapsed">

            <StackPanel>

                <TextBlock>This is the collapsed view</TextBlock>

            </StackPanel>

        </DataTemplate>

        <DataTemplate x:Key="Expanded">

            <StackPanel>

                <Label Content="Name"/>

                <sapv:ExpressionTextBox

                      HintText="Name"

                      Expression="{Binding Path=ModelItem.name,

                                           Mode=TwoWay,

                                           Converter={StaticResource ArgumentToExpressionConverter },

                                           ConverterParameter=In}"

                      OwnerActivity="{Binding Path=ModelItem}"

                      ExpressionType="s:String"/>

                <Label Content="Age"/>

                <sapv:ExpressionTextBox

                      HintText="Age"

                      Expression="{Binding Path=ModelItem.age,

                                         Mode=TwoWay,

                                         Converter={StaticResource ArgumentToExpressionConverter },

                                         ConverterParameter=In}"

                      OwnerActivity="{Binding Path=ModelItem}"

                      ExpressionType="s:Int32"/>

            </StackPanel>

        </DataTemplate>

        <Style x:Key="ExpandOrCollapsedStyle"

               TargetType="{x:Type ContentPresenter}">

            <Setter Property="ContentTemplate"

                    Value="{DynamicResource Collapsed}"/>

            <Style.Triggers>

                <DataTrigger Binding="{Binding Path=ShowExpanded}" Value="true">

                    <Setter Property="ContentTemplate" Value="{DynamicResource Expanded}"/>

                </DataTrigger>

            </Style.Triggers>

        </Style>

    </sap:ActivityDesigner.Resources>

    <Grid>

        <ContentPresenter Style="{DynamicResource ExpandOrCollapsedStyle}" Content="{Binding}" />

    </Grid>

</sap:ActivityDesigner>

It is like a face of our activity. But, how could the activity know which face it belong to? We place this attribute
    [Designer(typeof(PersonInfoActivityDesigner))]
Ahead of the PersonInfoActivity class:

Ok, that is all we need. This is the final structure:

blog comments powered by Disqus