WPFix Part 2 (Binding Extension)

This time, I will skip the introduction and jump right into technical stuff.

In the previous post, I tried to reduce XAML’s dependency to code files for even the simplest operations. There were a lot of ways other than my lambda converter. We could write a custom binding which could save a lot more of typing. However, my intention is not to type less, but to keep relevant parts together. Still typing less does not hurt, as long as it is clear. We will come back to this, but before that …

Problem 1

Suppose we have an adjustable background color. Don’t worry, I am not going to write another custom color picker for WPF. I will try to use the lambda converter.

1

2

3

4

5

6

7

8

9

10

11

12

13

<StackPanel>

<Sliderx:Name="Red"Value="255"Minimum="0"Maximum="255"/>

<Sliderx:Name="Green"Value="255"Minimum="0"Maximum="255"/>

<Sliderx:Name="Blue"Value="255"Minimum="0"Maximum="255"/>

<StackPanel.Background>

<MultiBinding Converter='{fix:Lambda

"r,g,b=>SolidColorBrush(Color.FromScRgb(1,r/255,g/255,b/255))"}'>

<Binding ElementName="Red"Path="Value"/>

<Binding ElementName="Green"Path="Value"/>

<Binding ElementName="Blue"Path="Value"/>

</MultiBinding>

</StackPanel.Background>

</StackPanel>

Parsing this lambda expression looks a bit harder. Multiple parameters are not a problem but SolidColorBrush and Color classes are.

Solution 1

Without any modification, Dynamic Expression API will throw an exception in this case. Luckily it is possible to construct predefined System types ( such as DateTime) with the API, and we already have a way to convert strings to types. IXamlTypeResolver is one of the two services provided by WPF at the ProvideValue method of any Markup Extension. All I had to do was to use this service and act as a last resort to the parser. You will be able to find the required changes to dynamic.cs at the new zipped solution. I surrounded the changes with regions named WPFix.

Now, the above code is working smoothly. If you had the opportunity to look into the dynamic.cs, you know that there are a lot ways to improve it. First thing that pops up is that the above expression is not even a valid lambda expression. There should be a new keyword before SolidColorBrush, but such conformance required more changes and does not bother me at all.

Problem 2

The amount of typing increased by a considerable margin (let me repeat that my intention is not to type less). This increase does not come along with clarity, also. In fact, we now have to keep bindings and parameters ordered.

Solution 2

Lets also provide an alternative to MultiBinding class which does not have a corresponding Markup Extension.

There are a few points to remark in the above code. The least interesting part is the Element Markup Extension. Please note that, this is not a complete alternative to a normal Binding with an ElementName. Path property of a Binding is not a simple string, and the code below does not treat it the way it should. Code speaks better sometimes.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

publicclassElementExtension:MarkupExtension

{

publicElementExtension(stringnameAndSimplePath)

{

this.Binding=newBinding();

intpi=nameAndSimplePath.IndexOf('.');

this.Binding.ElementName=nameAndSimplePath.Substring(0,pi);

this.Binding.Path=newSystem.Windows.PropertyPath(

nameAndSimplePath.Substring(pi+1,nameAndSimplePath.Length-pi-1));

}

publicoverride objectProvideValue(IServiceProvider serviceProvider)

{

returnthis.Binding.ProvideValue(serviceProvider);

}

privateBinding Binding;

}

Notice that I do not expect a IMultiValueConverter as a converter. The rationale is that, specified bindings are associated with parameter names and they belong to a lambda expression.

What gives us the ability to set r, g and b as properties, is that they really are properties of BindingExtension! Eventually, so are the other characters in the alphabet. Even the possibility of this idea was intriguing at first, but when I think about it, it looks like a natural way. We just want to associate a binding with a short literal that we can use in an expression, possibly many times.

Suggestions are welcome. Tell me what do you think about this approach?WPFix2 Solution (VS2008 Beta 2)Solution file is updated, thanks to the feed-back. I have to admit, I am surprised by the interest shown, at the very beginning at least .

Sorry for this late response. Notification mails were messed up.
Well there clearly is a problem with the parser. Although I made several changes, parser code is not very /*todo:find a politically correct adjactive*/.

Here is a quick fix I came up with, using the extension methods in part 3: