Remember when you started playing with WPF? Remember when you coded your first binding?

{Binding ElementName=slider, Path=Value}

and then remember what you wanted to do next? Something like this I'm sure...

{Binding ElementName=slider, Path=Value/2}

(in case you missed it, I'm trying to divide Value by 2). At least I know I've always yearned for basic expression support in WPF bindings.
Converters have always allowed you to do this but I've always found the process of creating a converter really interrupts my flow. I've since found ways to partly reduce the friction when using Converters but I'd be happier if I could just have support for expressions.

Long term readers of this blog will remember I'm a big fan of dynamic compilation and, particularly, Expressions which make Dynamic Compilation much easier. And so my idea for a Binding/Converter that supports expressions was born. And here it is:

Shipping with the Visual Studio 2008 C# samples (available on MSDN Code Gallery) was a rather neat file called Dynamic.cs that contains a neat type called System.Linq.Dynamic.DynamicExpression (not to be confused with the DynamicExpression type that will ship with .NET 4.0).

Saweet. This little program would dump '2.5' to the Console window. Nice (I was about to start writing my own Exprssion parsing algorithm so thanks to my colleagues Zulfiqar Ahmed and James World for introducing me to this little gem).

This is the key piece of magic but you can download the source (below) to get a full view of the current implementation.

More examples

The reason the InputType defaults to double is because I imagine that the vast majority of times you'll want to use this for some basic layout magic (ActualWidth / 2 etc). However, there are many scenarios where you may wish to change the InputType. For example, imagine we have a type called Item with two DateTime properties, CreatedDate and ModifiedDate:

And imagine we would like to highlight 'NEW' items, i.e. those where the ModifiedDate is equal to the CreatedDate and were created in the last week. Easy with the ExpressionConverter and a DataTrigger added to our DataTemplate:

Note, that in this case we have to specify the InputType. Also, we had to encode ampersand and less than in XML. So, did it work? Of course:

Performance

So, how does this stuff perform?

Well, not bad actually. The compilation of the expression is relatively slow but this only happens once per converter. Of course, experienced WPFers will know this could easily lead to terrible performance as, if within an DataTemplate used by an ItemsControl, the converter might be created hundreds of times, ouch!

This is why the ExpressionConverter has a Cache property which defaults to true. When Caching is on, compiled expressions are cached in a static dictionary and a matching expression (based on the Expression string and InputType) will always reuse this compiled expression. Note, if you have many different expressions. That is, the expressions are being generated at runtime, then you might leak memory and therefore may choose not to use the cache. Set the Cache property to false if you're worried about this - you will then incur a compilation per Converter. The solution here is to put the Converter high in the resource tree so it's only compiled once and used as a resource wherever needed:

Anyway, time for some rough figures about the speed of the expression itself. Here are the results for a million invocations of a reasonably complex Expression, "Math.Cos(x)/22+1/x":

The results you're interested in are the direct invoke and wrapped invoke. direct invoke (which took 269ms for a million invocations) is the same 'expression' as a raw function being invoked directly (note it included conversion to a double as required by an IValueConverter which takes an object parameter). The wrapped invoke represents the dynamically compiled expression also including the converstion to a double. This took 371ms for a million invocations. So it's slower, no suprise, but by a factor of about .3 in this test.

I should point out that, in some tests, the dynamic binding exhibited slower invocations of up to 4x but this really isn't the point. In most cases this performance would be more than adequate as the calculation of the expression (and the addition of the dynamic slowness) which totals a miniscule ~0.0004ms, clearly isn't going to be the bottleneck in your application's peformance. However, for performance sensitive scenarios where you might have thousands of ExpressionBindings, within an ItemsControl for example, you may want to skip this and go the old fashioned way and use a normal Binding and custom IValueConverter.

Comments are closed for this post.

Posted by
Rob
@
07 Jan 2010
9:01 AM
While it seams pretty cool, this sort of practice can lead to maintenance nightmares as you put more and more code into the Xaml. This is a prime example of violation of Separation of Concerns. The scenarios you describe are better solved using a View Model, where the code is easily discoverable, more maintainable, testable and reusable. That's not to say this idea has no value or isn't useful. I just think you should have a pretty good reason to forgo using a VM in favor of this.

Posted by
Josh Smith
@
07 Jan 2010
10:35 AM
I've seen several variations of this idea over the years, and the same discussion always comes up. As Rob pointed out, the separation of concerns can become "unseparated" too easily. I'm all in favor of using this kind of tool for things like layout tweaks, because writing one-off value converters is a pain. But, as you suggested, perhaps the DateTime example goes a little too far.

Nice job, though. Thanks for sharing this.

Posted by
Siderite
@
08 Jan 2010
1:54 AM
As mostly an ASP.Net programmer, I have been hit by the Bind/Eval nightmare on web pages. At first it seems like a good idea, then it gets more cumbersome as you want more complexity and then you end up placing all your code in a RowDatabound event anyway.

However, I do agree that I really dislike writing IValueConverters for banal things like not equal, less than, type conversion and so on. After all, one can abuse any tool, no matter how good the creator's intentions. Oppenheimer comes to mind :)

I rest assured that you will not become the destroyer of WPF for providing useful gizmos such as this, though. Good work!

IdentityMine (my employer) had a WPF converter using a similar concept, but with JavaScript as the expression language. This was before we got dynamic expressions in .NET (I think they published it around 2007).

I will probably include something like this in the MVVM Light Toolkit, but in the moment I am rather leaning towards the lambda converter one. I like the lambda syntax. Nice to see another implementation though.

Cheers,Laurent

Posted by
Thomas
@
05 Dec 2011
9:01 PM
i am trying to use this in Silverlight, but SL does not support DynamicExpression.ParseLambda() , anyone knowns a workaround ?