Thursday, June 9, 2011

Silverlight 4 Value Converter Properties

An interesting problem I faced recently was how to give a Value Converter class access to "data" (strings, ints, bools, lists, collections, etc). I thought about this for a while, and I firstly figured I could probably give the Value Converter access to whatever data it needed through its own view model. I thought about this some more and decided wouldn't it be cool if I could just declare properties in my Value Converter class and bind those properties to data in my xaml's view model, thus keeping my Value Converter a fairly light object. At that time there wasn't much literature around suggesting that this was even possible, much less any examples, so I went about it my own way.

I had also been recently looking at binding to dependency properties (Silverlight 4 Custom Property Binding), so it was something I had fresh in my mind. I knew that to register a DependencyProperty the owner needed to inherit from the DependencyProperty base class. So as well as implementing the usual IValueConverter interface, I made my class inherit from DependencyObject like so:
public class CustomValueConverter : DependencyObjectIValueConverter 

I then declared a couple of dependency properties in my class; firstly a Dictionary<intstring> LookupDictionary and secondly a bool UpperCase , like so:
public static readonly DependencyProperty 
LookupDictionaryProperty = DependencyProperty.Register
(
    "LookupDictionary",
    typeof(Dictionary<intstring>),
    typeof(CustomValueConverter),
    null
);
 
public Dictionary<intstring> LookupDictionary
{
    get { return (Dictionary<intstring>)GetValue(LookupDictionaryProperty); }
    set { SetValue(LookupDictionaryProperty, value); }
}
 
public static readonly DependencyProperty UpperCaseProperty DependencyProperty.Register
(
    "UpperCase",
    typeof(bool),
    typeof(CustomValueConverter),
    null
);
 
public bool UpperCase
{
    get { return (bool)GetValue(UpperCaseProperty); }
    set { SetValue(UpperCaseProperty, value); }
}

The next thing I wanted to do was actually use the properties in my Convert method, so as an example I did something like this:
public object Convert(object 
value, Type targetType, object parameter, CultureInfo culture)
{
    string lookup = string.Empty;
    if (!(value == null || LookupDictionary == null))
    {
        if (value is int)
        {
            if (UpperCase)
                lookup = LookupDictionary[(int)value].ToUpper();
            else
                lookup = LookupDictionary[(int)value];
        }
    }
    return lookup;
}

That's basically all you need to be able use your converter in your xaml, and set values for the properties we have declared in it.

Here is the entire example of the Value Converter class example:
using System;
using System.Windows;
using System.Windows.Data;
using System.Globalization;
using System.Collections.
Generic;
 
public class CustomValueConverter : DependencyObjectIValueConverter
{
    public static readonly DependencyProperty LookupDictionaryProperty = DependencyProperty.Register
    (
        "LookupDictionary",
        typeof(Dictionary<int, string>),
        typeof(CustomValueConverter),
        null
    );
 
    public Dictionary<intstring> LookupDictionary
    {
        get { return (Dictionary<intstring>)GetValue(LookupDictionaryProperty); }
        set { SetValue(LookupDictionaryProperty, value); }
    }
 
    public static readonly DependencyProperty UpperCaseProperty = DependencyProperty.Register
    (
        "UpperCase",
        typeof(bool),
        typeof(CustomValueConverter),
        null
    );
 
    public bool UpperCase
    {
        get { return (bool)GetValue(UpperCaseProperty); }
        set { SetValue(UpperCaseProperty, value); }
    }
 
 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string lookup = string.Empty;
        if (!(value == null || LookupDictionary == null))
        {
            if (value is int)
            {
                if (UpperCase)
                    lookup = LookupDictionary[(int)value].ToUpper();
                else
                    lookup = LookupDictionary[(int)value];
            }
        }
        return lookup;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 
}}

No comments:

Post a Comment