(WF4) ExpressionTextBox Expression Property and ArgumentToExpressionConverter

There are many examples of binding ETB, but I notice they tend to be short on the details of why the example code looks as it does. Maybe it is because we are short on the ‘why’ that people can get a little lost once they want to do something other than the well-documented scenarios (e.g. In/OutArgument binding.)

Today I’m going to describe the actual data flow in binding an ETB to an argument or expression, so you can visualize in your head everything involved in binding an ETB, and hopefully this makes debugging ETB bindings easier for you.

Let’s begin by saying ‘hello’ to a canonical example - InArgument<T> on a custom activity designer:

<sap:ActivityDesigner x:Class="ActivityLibrary1.ETBExample"

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

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

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

   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">

    <sap:ActivityDesigner.Resources>

        <ResourceDictionary>

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

        </ResourceDictionary>

    </sap:ActivityDesigner.Resources>

    <Grid>

        <sapv:ExpressionTextBox

           Expression="{Binding Path=ModelItem.FooValue,

               Mode=TwoWay,

               Converter={StaticResource ArgToExpConverter},

               ConverterParameter=In }"

           ExpressionType="s:String"

           OwnerActivity="{Binding Path=ModelItem}"

          />

    </Grid>

</sap:ActivityDesigner>

In Pictures

What data flow is being described by the XAML above? Let’s visualize:

image

The binding is a back-and-forth pipeline between two properties

A.  ExpressionTextBox.Expression. This is a dependency property (see also: ExpressionTextBox.ExpressionProperty) of type ModelItem.

to

B.  The ‘FooReference’  property on the custom CodeActivity (or its ModelItem). [The reality is that the binding’s property path refers to a ‘FooReferenceModelProperty, which refers to a ModelItem. That ModelItem wraps the actual value of the FooReference property. Don’t worry about this part if you didn’t understand it, you can read it again later.]

So, point #1: The WPF binding is really dealing with ModelProperty/ModelItems, not the wrapped objects inside those ModelItems. i.e. ETB knows how to display an Expression wrapped in a ModelItem, it doesn’t know how to display an Expression CLR object.

And point #2: The converter in the middle is called ‘ArgumentToExpressionConverter’. But really it’s converting ModelItems to ModelItems. Isn’t that naming confusing?

Yes.

And no. Because those ModelItems aren’t just any model items. Those ModelItems have to contain specific stuff – and funnily, in this example, they contain Arguments, and Expressions.

To clarify the diagram, let’s pretend ModelItem is a pseudo-generic type.  To make it a little obvious we are only pretending and ModelItem is not really generic, we’ll use a funny notation:

ModelItem {of T} ”.

Now we can draw a new & improved diagram:

image

Cool. But wait! There’s still one more oddity in this diagram.

The diagram reads ‘Activity<ExpressionType> ’, not ‘Expression<ExpressionType>’ . What’s up with that?

 

In WF4, Expressions = Activities

The WF4 the model for representing runtime expressions, which are just computations with an output value, is to represent them as Activities with an OutArgument<T> named Result. And in order to provide strong typing to indicate that they provide such a result, they should inherit from Activity<T>.

In fact there is a whole slew of ‘expression activities’ in the .Net Framework. There are the ‘declarative expression activities’ in System.Activities.Expressions namespace, which include most of the primitive expressions you would expect from a programming language – Add, Subtract, And, Or, etc.

However, you will never be generating expressions of these types by using an ExpressionTextBox. An ETB only generates a few expressions (activities): VisualBasicValue<T>, VisualBasicReference<T>, and Literal<T>.

 

Knowledge into Practice

If you’re bored, quit reading now, but if you’re still working on internalizing what you just read here’s a textbook style quiz:

Q1. How would you bind an ExpressionTextBox to an Activity<bool> like e.g. the While activity designer?

Q2. What might the (strangely named) ArgumentToExpressionModelItemConverter class actually do here? [jump to: forum thread about ETB in property grid]

Answers:

A1. In this case there is no need for a converter at all. Both sides speak the same language: ModelItem {of Activity<T>}

A2. In the linked thread, ArgumentToExpressionModelItemConverter needs to be achieving a similar goal as ArgumentToExpressionConverter: it must convert something to ModelItem{of Activity<T>} so that it can bind the ExpressionTextBox.Expression.

The significant difference is on the input side in that a) it is a IMultiValueConverter b) it requires special inputs, which can be deduced (from the example code in the thread) to be:

a) ‘PropertyValue.Value’ - which is a PropertyValue – this is only used in the reverse binding direction, for updating the property value once the expression has been changed
b)
PropertyValue.ParentProperty’ - which is a PropertyEntry. Actually it must be a ModelPropertyEntry.