Tagged: .net

In my last post we saw, that though it is possible to bind to a bound property, some implicit type conversions might occur. We can however create a custom type converter and bring a little more predictability into the way the type conversions happen.

We start by creating a class that implements the IValueConverter interface (found in System.Windows.Data). As part of the implementation we define two methods Convert – which is responsible for converting the source data type to destination data type and ConvertBack which is its antithesis. In the context of our example from the last post, Convert will take a SolidColorBrush and give us a String (the proper name of a color rather than its hex value). ConvertBack will do the reverse – the implementation being left as an exercise for the reader :-) .

Here is what the code looks like:

using System;
using System.Windows.Media;
using System.Windows.Data;
using System.Globalization;


namespace TypeConversion
{
  class ColorToStringConverter : IValueConverter
  {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
      if (null != value)
      {
        System.Windows.Media.Color MColor;
        MColor = ((SolidColorBrush)value).Color;


        switch(MColor.ToString().ToLower())
        {
          case “#ffff0000″:
           return “Red”;
          case “#ff00ff00″:
           return “Lime”;
          case “#ff008000″:
           return “Green”;
          case “#ff0000ff”:
           return “Blue”;
          default:
           return MColor.ToString();
        }
      }
      else
      {
        return “bad color”;
      }
    }


    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
      throw new NotSupportedException();
    }
  }
}

The code for conversion is a little inelegant for my taste. I wish there was a better way of doing this. I tried converting System.Windows.Media.Color to System.Drawing.Color and then using System.Drawing.Color.ToKnownColor(). Sadly, that works only if System.Drawing.Color was initialized using a System.Drawing.KnownColor enumeration member in the first place. One could build a look-up table to find the English name of a color given its Hex value but I didn’t bother.

Now in order to use this class we need to make some modifications to our XAML code:

<Page xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:local=”clr-namespace:TypeConversion”
HorizontalAlignment=”Center”
VerticalAlignment=”Center”>
    <Page.Resources>
        <Local.ColorToStringConverter x:Key=”TheConverter”>
    </Page.Resources>

    <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, Converter={StaticResource TheConverter}}” Margin=”2,2,2,2″/>
    </StackPanel>
</Page>

Basically, we first instantiate our type converter class as a static resource and then refer to it as part of the binding expression. You’ll also need to compile this XAML and the converter class into either an XBAP or a windows application. I have uploaded the pre-built XBAP which you can run now (IE only) or download the Visual Studio project and play with it.

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.

Server.XmlEncode?

Mar 21, 2007

While looking for Server.XmlEncode (there is none as of ASP.NET 2.0) , I came across the Microsoft Anti Cross-Site Scripting Library. The library also has two other interesting methods – JavaScriptEncode and VisualBasicScriptEncode, besides different implementations of UrlEncode and HtmlEncode. Now if only they would add a SqlEncode…