Embed code in XAML

Loads of time I needed a converter that does a very small operation such as binding to the Height of an element and subtract 10 from the binded value. Every time you have to create a converter to do so. I must admit, it really makes me angry because I would like to this in XAML.

I found this cool code sample on Dynamic Expression API from msdn and I thought why don’t I use it to be able to embed code in XAML…. Apparently I am not the first one trying this out . While having a chat with WPF Guru, Josh Smith, he pointed out that someone else created something similar. M. Orçun Topdağı did a very great job in creating converters that can be declared in XAML. Great Job dude!!! It is really unfortunate that I found out about this after I created my own :(

Anyway now that I did it might as well show it to you guys right :) So basically this is quite simple. I created a Markup Extension called LambdaValueConverter that creates an instance of a converter that accepts a LambdaExpression which is then compiled (using the Dynamic Expression API) and run whenever the binding for the converter changes. In order to use this LambdaValueConverter you have to pass the Lambda Expression that you want to evaluate when the binding changes. Let me give you an example. Imagine you want to bind to the Height property of a Grid and divide it’s height by 2 and subtract 20. You would do something like this in the Binding

Binding Lambdas1

As you can see this is quite easy to use… It is important to note that param is a predefined variable that holds the binding value (in the case of this example it will be a Double since we are binding to the height property of a Grid). In the expression you can write anything that is supported in the Dynamic Expression API.

One handy feature I added, is support for strings. Imagine you want to concatenate a string with a binding value. Instead having to create 2 TextBlocks and loads of other things, all you have to do is to enter the text you want + the param that is supplied to you by the converter. You have to surround your string with the $ symbol(don’t ask why I choose this symbol :D ) in order for the parser to know that the specified text is a string. It would look something like this….

Binding Lambdas2

So as you can imagine the output of this binding will be >> The border size is {the value of the binding}.

Cool…. Yet I wanted to go a step further. Basically I asked myself and said, “where can this fit besides for converters” and BAMM… I said what about having such a feature for the CanExecute of commands.. Usually in the can execute of a command all you do is a one line of code yet you have to create an event handler every time (same problem as converters!) So I created a class that inherits from the CommandBinding class and extended it to support a expression string that can be evaluated as the CanExecute event handler. In order to use this all you have to do is, create an instance of the CommandLambdas class and set the CanExecuteExpression property with a string that is your expression. As context of the expression there are two predefined variables that you can use. param that is the parameter that you are passing for the command and e that is the CanExecuteRoutedEventArgs for the CanExecute event. Lets make an example. Imagine that you have a checkbox that determines if the Command for a button can execute or not. The code for the Button would look something like this

Binding Lambdas3

Just for the sake of the demo I used the Application.New command so that I don’t have to create my own :D Ok, so here we are setting the checkbox as our parameter for the command. Now all we have to do is to declare our command binding. We have to declare a CommandLambdas and set the CanExecuteExpression property. Something like this….

Binding Lambdas4

So what we are doing is to check if the checkbox (that is our command parameter) is checked and if it is, we set the CanExecute. The assignment of the CanExecute is being done for us implicitly by the CommandLambdas class.

Updated: I found this brilliant Library called Blendables… in Blendables there is a very impressive feature called SimpleBinding and Complex Binding (among others) that enable you to write code in the binding in a very clean way… much more nice + powerful than what I did here….

So you can do something like this in the binding

Width={blendables:EvalBinding [{Self}.Height]/2}

That’s nice isn’t it…. Have a look at their Documentation here. Or even check out their samples over here.

Well that is all… I am looking forward for feedback to see how we can extend even more this to be even more useful for WPF Developers :)

Looking forward for your feedback.

See also Filterering CollectionViewSource Dynamically

Download Source Code for the AvalonLambdas

kick it on DotNetKicks.com

About these ads

20 thoughts on “Embed code in XAML

  1. Pingback: How can I concatenate a string and a Binding value in a TextBlock « C# Disciples

  2. This is very interesting. I have to be careful not to add too much logic to my XAML, otherwise we’ll be back in the old ASP programming model all over again… :)

    Thanks,
    Josh

  3. Hi Josh,

    Actually you cannot add too much logic because you are limited to 1 line of code :)
    All you can do is manipluate the given value and return the new value … for example you receive 500 and you divide by 2(in case of the converter)…. for the can execute all you can do is return a boolean.

    So if you need complex logic you still have to use code behind …

    Regards

  4. Pingback: Filtering CollectionViewSource Dynamically « C# Disciples

  5. thats really cool but I bet the performance wise is a bit slow… I tried that approach with the CodeDom but it was a bit to slow for me…. The differnce with that is that it gives you more option on what you can do because you can put any code you want inside there…
    Nice find thanks for sharing it …

  6. Pingback: next best geek » Blog Archive » WPF: Code in XAML -> Width={Binding Height}*2?

  7. That sounds very nice :)
    The link to your zip file is broken, could you please fix it so that I could have a look to the code ?

    Thanks

  8. Hi Marlon, I’m fiddling around with this kind of thing and I think I may have found a little glitch in your code–either that or I’m totally missing something.

    When you pass the expression to the parser/compiler thing, you are also passing a type along with it. But the type you pass is the target type of the converter, when I think it should actually be the type of the INPUT. So if I were trying to convert a TextBox to a Visibility, “param” would show up as a Visibility, instead of a TextBox, and I was getting a runtime exception.

    On that note, I was trying to do this, and ran into a problem where I couldn’t actually return a visibility in the lambda expression because “System” is an unrecognized identifier.

    Any thoughts?

  9. Turns out Orcun had a partial solution to this in his next post. I still don’t understand what’s going on, but something to do with registering the dynamic lambda interpreter to recognize type names via IXamlTypeResolver or something like that.

    Unfortunately it still doesn’t work with Visibility because it appears to not handle enums! Argh.

  10. Pingback: Docking WPF controls to right or bottom of a Canvas « Richards blog

  11. Pingback: WPF Lambda converter extension & Converter Library « János Janka

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s