Binding a custom activity property to a designer control

Binding a text box designer control to an activity argument is fairly straightforward; binding a complex designer control (such as a combo box) to an activity argument may present challenges, however. This topic discusses how to bind an activity argument to a combo box control on a custom activity designer.

Creating the combo box item converter

  1. Create a new empty solution in Visual Studio called CustomProperty.

  2. Create a new class called ComboBoxItemConverter. Add a reference to System.Windows.Data, and have the class derive from IValueConverter. Have Visual Studio implement the interface to generate stubs for Convert and ConvertBack.

  3. Add the following code to the Convert method. This code converts the activity's InArgument<T> of type String to the value to be placed in the designer.

    ModelItem modelItem = value as ModelItem;
    if (value != null)
    {
        InArgument<string> inArgument = modelItem.GetCurrentValue() as InArgument<string>;
    
        if (inArgument != null)
        {
            Activity<string> expression = inArgument.Expression;
            VisualBasicValue<string> vbexpression = expression as VisualBasicValue<string>;
            Literal<string> literal = expression as Literal<string>;
    
            if (literal != null)
            {
                return "\"" + literal.Value + "\"";
            }
            else if (vbexpression != null)
            {
                return vbexpression.ExpressionText;
            }
        }
    }
    return null;
    

    The expression in the above code snippet can also be created using CSharpValue<TResult> instead of VisualBasicValue<TResult>.

    ModelItem modelItem = value as ModelItem;
    if (value != null)
    {
        InArgument<string> inArgument = modelItem.GetCurrentValue() as InArgument<string>;
    
        if (inArgument != null)
        {
            Activity<string> expression = inArgument.Expression;
            CSharpValue<string> csexpression = expression as CSharpValue<string>;
            Literal<string> literal = expression as Literal<string>;
    
            if (literal != null)
            {
                return "\"" + literal.Value + "\"";
            }
            else if (csexpression != null)
            {
                return csexpression.ExpressionText;
            }
        }
    }
    return null;
    
  4. Add the following code to the ConvertBack method. This code converts the incoming combo box item back to an InArgument<T>.

    // Convert combo box value to InArgument<string>
                string itemContent = (string)((ComboBoxItem)value).Content;
                VisualBasicValue<string> vbArgument = new VisualBasicValue<string>(itemContent);
                InArgument<string> inArgument = new InArgument<string>(vbArgument);
                return inArgument;
    

    The expression in the above code snippet can also be created using CSharpValue<TResult> instead of VisualBasicValue<TResult>.

    // Convert combo box value to InArgument<string>
                string itemContent = (string)((ComboBoxItem)value).Content;
                CSharpValue<string> csArgument = new CSharpValue<string>(itemContent);
                InArgument<string> inArgument = new InArgument<string>(csArgument);
                return inArgument;
    

Adding the ComboBoxItemConverter to the custom designer of an activity

  1. Add a new item to the project. In the New Item dialog, select the Workflow node and select Activity Designer as the type of the new item. Name the item CustomPropertyDesigner.

  2. Add a Combo Box to the new designer. In the Items property, add a couple of items to the combo box, with Content values of "Item1" and 'Item2".

  3. Modify the XAML of the combo box to add the new item converter as the item converter to be used for the combo box. The converter is added as a resource in the ActivityDesigner.Resources segment, and specifies the converter in the Converter attribute for the ComboBox. Note that the namespace of the project is specified in the namespaces attributes for the activity designer; if the designer is to be used in a different project, this namespace will need to be changed.

    <sap:ActivityDesigner x:Class="CustomProperty.CustomPropertyDesigner"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:c="clr-namespace:CustomProperty"
        xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
        xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation">
    
        <sap:ActivityDesigner.Resources>
            <ResourceDictionary>
                <c:ComboBoxItemConverter x:Key="comboBoxItemConverter"/>
            </ResourceDictionary>
        </sap:ActivityDesigner.Resources>
        <Grid>
            <ComboBox SelectedValue="{Binding Path=ModelItem.Text, Mode=TwoWay, Converter={StaticResource comboBoxItemConverter}}"  Height="23" HorizontalAlignment="Left" Margin="132,5,0,0" Name="comboBox1" VerticalAlignment="Top" Width="120" ItemsSource="{Binding}">
                <ComboBoxItem>item1</ComboBoxItem>
                <ComboBoxItem>item2</ComboBoxItem>
            </ComboBox>
        </Grid>
    </sap:ActivityDesigner>
    
  4. Create a new item of type CodeActivity. The default code created by the IDE for the activity will be sufficient for this example.

  5. Add the following attribute to the class definition:

    [Designer(typeof(CustomPropertyDesigner))]
    

    This line associates the new designer with the new class.

The new activity should now be associated with the designer. To test the new activity, add it to a workflow, and set the combo box to the two values. The properties window should update to reflect the combo box value.