Entries from June 2007 ↓

Binding To A Bound Property

During my WPF DataBinding sessions at TechMela, one of the attendees asked me if it was possible to have a property of a control bound to a property of another control which is already bound. It is indeed possible. Let us start with the following scenario:

<Page xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
HorizontalAlignment=”Center”
VerticalAlignment=”Center”>
    <StackPanel Width=”400″>
        <TextBox x:Name=”txtColor” BorderBrush=”Black” Text=”Type a color” Margin=”2,2,2,2″/>
        <Rectangle x:Name=”rectColor” Height=”100″ Fill=”{Binding ElementName=txtColor, Path=Text, Mode=OneWay}” Margin=”2,2,2,2″ Stroke=”Silver”/>

    </StackPanel>
</Page>

Our UI consists of a TextBox and a Rectangle. The Rectangle’s Fill property is bound to the TextBox’s Text property. Each time you type a valid color name in the TextBox, the color of the Rectangle changes to it. Typing Blue in the TextBox will get you a Blue Rectangle (it would work for any color defined in System.Windows.Media.Colors class). This is what you get when you paste the code above in XamlPad and type in Maroon into the TextBox:

TextBox + Rectangle in XamlPad

If you are running Windows Vista or have .NET Framework 3.0 installed on Windows XP/Windows Server 2003, you can directly run the XAML in your browser:

Stage I: Basic UI with a TextBox and a Rectangle

This works because behind the scenes the Text property (a string) is being automatically converted to a SolidColorBrush (which is what the Rectangle’s Fill property is). In fact, if you are debugging this in Visual Studio, you’ll see Exceptions in the Output window for every character you type that results in an invalid color. For instance, while you are typing Blue, you’ll get 3 exceptions (B, Bl, Blu are all invalid color names):

System.Windows.Data Error: 6 : ‘TargetDefaultValueConverter’ converter failed to convert value ‘B’ (type ‘String’); fallback value will be used, if available. BindingExpression:Path=Text; DataItem=’TextBox’ (Name=’txtColor’); target element is ‘Rectangle’ (Name=’rectColor’); target property is ‘Fill’ (type ‘Brush’) FormatException:’System.FormatException: Token is not valid.
at MS.Internal.Parsers.ParseBrush(String brush, IFormatProvider formatProvider, ITypeDescriptorContext context)



and so on for Bl and Blu…

It is this very type conversion infrastructure that supports XAML; allowing us to transparently assign the name of a color (a string) to the Rectangle tag’s Fill attribute.

We’ll now introduce another TextBox into our UI. The new TextBox’s Text property is going to be bound to the Rectangle’s Fill property (which we’ve already bound to another TextBox in the last example). Here is how the updated code will look like:

<Page xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
HorizontalAlignment=”Center”
VerticalAlignment=”Center”>
    <StackPanel Width=”400″>
        <TextBox x:Name=”txtColor” BorderBrush=”Black” Text=”Type a color” Margin=”2,2,2,2″/>
        <Rectangle x:Name=”rectColor” Height=”100″ Fill=”{Binding ElementName=txtColor, Path=Text, Mode=OneWay}” Margin=”2,2,2,2″ Stroke=”Silver”/>
        <TextBox x:Name=”txtTextColor” BorderBrush=”Black” Text=”{Binding ElementName=rectColor, Path=Fill, Mode=OneWay}” Margin=”2,2,2,2″/>
    </StackPanel>
</Page>

And this is how the things look like now in XamlPad:

TextBox + Rectangle in XamlPad

Again, if you have .NET Framework 3.0 installed, let us run the app first before moving on:

Stage II: TextBox with its Text property bound to the Rectangle’s Fill property

When you type the name of a color into the first TextBox (txtColor) now, you’ll see that the Text property of the TextBox we’ve just introduced (txtTextColor), updates automatically. However, you will not see it set to the same text that you’ve entered into txtColor. Instead you’ll see the color represented as hexadecimal. This is because txtTextColor’s property is bound to the Rectangle’s Fill property. The text entered into txtColor has been automatically converted to a SolidColorBrush in order to be able to bind to the Fill property. When you try to convert a SolidColorBrush back to a string to bind to txtTextColor’s Text property you don’t get the same “English” color name that you entered.

Moral of the story – by the time data cascades down to its final destination it might undergo type conversion(s). Of course the caveat is applicable only when a binding exists between incompatible types. In my next post, we’ll take this type conversion business into our own hand and try to restore the “fidelity” of a Text → SolidColorBrush → Text conversion using our custom IValueConverter class.