Click here to Skip to main content
15,885,985 members
Articles / Desktop Programming / WPF

WPF: Dictionary Value Converter

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
10 Aug 2011Ms-PL1 min read 21.5K   4   1
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.

XML
<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:

C#
public static class BooleanValues
 {
     public const bool True = true;
     public const bool False = false;
 }
XML
<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:

C#
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

License

This article, along with any associated source code and files, is licensed under The Microsoft Public License (Ms-PL)


Written By
Software Developer (Senior) Verint
Israel Israel
Arik Poznanski is a senior software developer at Verint. He completed two B.Sc. degrees in Mathematics & Computer Science, summa cum laude, from the Technion in Israel.

Arik has extensive knowledge and experience in many Microsoft technologies, including .NET with C#, WPF, Silverlight, WinForms, Interop, COM/ATL programming, C++ Win32 programming and reverse engineering (assembly, IL).

Comments and Discussions

 
QuestionSeems like a rehash of... Pin
SledgeHammer0111-Aug-11 5:01
SledgeHammer0111-Aug-11 5:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.