65.9K
CodeProject is changing. Read more.
Home

WPF: Dictionary Value Converter

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1 vote)

Aug 10, 2011

Ms-PL

1 min read

viewsIcon

22150

WPF: Dictionary Value Converter

What’s the Story?

You want to convert an enum value to a bitmap image.

That’s Easy, Here’s a Solution

Usually you would simply create a new value converter which has some custom code (e.g. a switchcase statement) to convert from the enum value to the relevant image.

Is There a Better Solution?

How many times have you written this kind of converter, the kind that takes a value and maps it to another value?

Well, no more!

I present to you: DictionaryValueConverter. A Converter that lets you define a collection of key-value pairs and do the mapping for you.

So, How Can I Use this Converter?

The following code provides a common usage of this converter. Here, I map three enum values to three different bitmap images. Each value in the Values property is another image which is mapped by its x:Key.

<converters:DictionaryValueConverter x:Key="propertyTypeToImage">
    <converters:DictionaryValueConverter.Values>
        <BitmapImage x:Key="{x:Static local:PropertyType.Name}" UriSource="Name.png" />
        <BitmapImage x:Key="{x:Static local:PropertyType.Age}" UriSource="Age.png" />
        <BitmapImage x:Key="{x:Static local:PropertyType.Phone}" UriSource="Phone.png" />
    </converters:DictionaryValueConverter.Values>
</converters:DictionaryValueConverter>

This is SO COOL, Can I Use It Also to Convert Booleans to Visibility?

Well, yes and no.

Theoretically, it will work. There is nothing in the code which prevents it.

Practically, you need a way to specify the “true” and “false” Boolean values as the keys.

Unfortunately, XAML 2006 doesn’t allow x:Key to have complex values (using property element syntax). This was fixed in XAML 2009, but WPF doesn’t support it yet.

To work around it, you can define constants for the “true” and “false” values and use x:Static markup extension to provide the keys.

For example:

public static class BooleanValues
 {
     public const bool True = true;
     public const bool False = false;
 }
<converters:DictionaryValueConverter x:Key="booleanToVisibilityConverter">
    <converters:DictionaryValueConverter.Values>
        <Visibility x:Key="{x:Static local:BooleanValues.True}">Visible</Visibility>
        <Visibility x:Key="{x:Static local:BooleanValues.False}">Collapsed</Visibility>
    </converters:DictionaryValueConverter.Values>
</converters:DictionaryValueConverter>

So, How Is It Implemented?

Like this:

 using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Windows;
 using System.Windows.Data;
 
 namespace Common.Converters
 {
     public class DictionaryValueConverter : IValueConverter
     {
         /// <summary>
         /// Store the key type.
         /// Setting this property is needed if your key is an enum and  
         /// </summary>
         public Type KeyType { get; set; }
 
         /// <summary>
         /// Store the key-value pairs for the conversion
         /// </summary>
         public Dictionary<object, object> Values { get; set; }
 
         public DictionaryValueConverter()
         {
             Values = new Dictionary<object, object>();
         }
 
         public object Convert
         (object value, Type targetType, object parameter, CultureInfo culture)
         {
             // if key type is not set, get it from the first dictionary value, 
             // usually it's the same for all the keys
             if (KeyType == null)
             {
                 KeyType = Values.Keys.First().GetType();
             }
 
             // if key type is an enum
             if (KeyType.IsEnum)
             {
                 // convert integral value to enum value
                 value = Enum.ToObject(KeyType, value);
             }
 
             // if dictionary contains the requested key
             if (Values.ContainsKey(value))
             {
                 // return the relevant value
                 return Values[value];
             }
 
             // otherwise, don't return a value, 
             // this will fall back to the binding FallbackValue
             return DependencyProperty.UnsetValue;
         }
 
         public object ConvertBack
         (object value, Type targetType, object parameter, CultureInfo culture)
         {
             // no support for converting back
             return DependencyProperty.UnsetValue;
         }
     }
 }

You can download a demo application here.

That’s it for now,
Arik Poznanski