Silverlight & XAML Playground
about XAML and other Amenities

A generic enum converter to map values...

2010-09-03T16:38:49+01:00 by Andrea Boschin

Many times I have to deal with enumerated values with databinding, and often this requires  the writing of a converter to map the enum to something else. As an example you can have a Status enum and you need to transform it to a color (or a brush) in the UI, or you have a series of values from the enumerator and need to change it to an image when it is presented to the user.

Finally these days I found a generic solution to these problems that let me create a mapping from a value (an enumerator, a series of integers, of also a boolean) to an instance of another object. To give you an example think at having this enumerator:

   1: public enum MessageType
   2: {
   3:     Normal,
   4:     Urgent,
   5:     Critical
   6: }

We want to map the values to a series of colors having White for Normal, Orange for Urgent and Red for Critical. Since usually you can override IValueConverter and write a specific converter that handles this enum I found useful to create a parametric value converter that lets me write the code below:

   1: <UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   2:              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   3:              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
   4:              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:              xmlns:cv="clr-namespace:SilverlightPlayground.Converters;assembly=SilverlightPlayground"
   6:              mc:Ignorable="d" x:Class="SilverlightPlayground.MyApplication.Shell" d:DesignWidth="456">
   7:     <UserControl.Resources>
   8:         <cv:EnumConverter x:Key="mapTypeToBrush">
   9:             <cv:EnumConverter.Items>
  10:                 <SolidColorBrush Color="#00000000" />
  11:                 <SolidColorBrush Color="#FFFF9900" />
  12:                 <SolidColorBrush Color="#FFFF0000" />
  13:             </cv:EnumConverter.Items>
  14:         </cv:EnumConverter>
  15:     </UserControl.Resources>
  16:     <Grid x:Name="LayoutRoot">
  17:         <Rectangle Fill="{Binding ReveivedMessageType, Converter={StaticResource mapTypeToBrush}}" Width="100" Height="100" />
  18:     </Grid>
  19: </UserControl>

The beautiful of this converter is that with a single converter you can create a series of mappings in the App.xaml resources and share them across all the applications and centralize the conversion of application wide enums in a single position. The code of the converter is really simple and straightforward:

   1: public class EnumConverter : IValueConverter
   2: {
   3:     private List<object> items;
   4:  
   5:     public List<object> Items 
   6:     { 
   7:         get
   8:         {
   9:             if (items == null)
  10:                 items = new List<object>();
  11:  
  12:             return items;
  13:         }
  14:     }
  15:  
  16:     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  17:     {
  18:         if (value == null)
  19:             throw new ArgumentNullException("value");
  20:         else if (value is bool)
  21:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  22:         else if (value is byte)
  23:             return this.Items.ElementAtOrDefault(System.Convert.ToByte(value));
  24:         else if (value is short)
  25:             return this.Items.ElementAtOrDefault(System.Convert.ToInt16(value));
  26:         else if (value is int)
  27:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  28:         else if (value is long)
  29:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  30:         else if (value is Enum)
  31:             return this.Items.ElementAtOrDefault(System.Convert.ToInt32(value));
  32:  
  33:         throw new InvalidOperationException(string.Format("Invalid input value of type '{0}'", value.GetType()));
  34:     }
  35:  
  36:     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  37:     {
  38:         if (value == null)
  39:             throw new ArgumentNullException("value");
  40:  
  41:         return this.Items.Where(b => b.Equals(value)).Select((a, b) => b);
  42:     }
  43: }

The converter has a list of items it use to make the conversion of integer values. It maps the integer to the index of the list and returns the n-th element found in the array. I didn't handled the out of bounds exception just because the errore returned to the user by the converter is already good to understand what it happen. The converter itself can handle both the directions if the Equals method is correctly overrided.

Finally, I  supported boolean values so it is possible to pass to the converter true/false and having it select the items from a list of two elements. This let me also map the Visibility to boolean values (that is a pretty frequent situation):

   1: <cv:EnumConverter x:Key="bool2Visibility">
   2:     <cv:EnumConverter.Items>
   3:         <Visibility>Collapsed</Visibility>
   4:         <Visibility>Visible</Visibility>
   5:     </cv:EnumConverter.Items>
   6: </cv:EnumConverter>

As you can see the trick is really simple but as usual simple things are the most beautiful and useful. I hope someone can judge this tip good to spare time. It has been very great for me.

Comments (5) -

January 14. 2012 18:56

Hey random online blogger person, be my valentine? Just joking, but you've got a great writing style. If you weren't a figment of my imagination, I'd write you poems and such.

Lauren Asplund

January 25. 2012 04:11

I needed to draft you that little note in order to thank you so much again about the fantastic things you\\\'ve documented on this website. This is certainly wonderfully open-handed with you to grant easily what exactly most of us would have marketed for an electronic book in order to make some cash on their own, most notably given that you could possibly have tried it in case you decided. These suggestions as well worked to be a good way to be certain that other people have similar eagerness much like my own to understand many more with reference to this problem. I am certain there are numerous more pleasurable situations ahead for those who view your blog post.

SEO

January 25. 2012 04:11

I wanted to draft you that little bit of observation to finally say thanks as before over the spectacular guidelines you have discussed at this time. It is so seriously open-handed with you in giving unreservedly all a few people could have offered for sale as an electronic book to help with making some cash for themselves, most importantly seeing that you could have tried it if you wanted. The ideas as well worked to be a easy way to be sure that other people online have the identical desire just as mine to figure out whole lot more on the subject of this problem. Certainly there are millions of more pleasurable situations in the future for people who read carefully your website.

SEO

January 25. 2012 04:11

I intended to post you a very small word to help thank you so much once again with the precious secrets you\\\'ve discussed at this time. This is simply tremendously generous of people like you to give freely exactly what a number of people could have marketed for an electronic book to end up making some dough for their own end, mostly considering that you could possibly have done it if you considered necessary. The inspiring ideas additionally worked to become a fantastic way to be aware that many people have similar keenness the same as my personal own to understand a great deal more around this condition. I am certain there are many more fun situations ahead for folks who discover your website.

SEO

January 25. 2012 04:12

I wanted to compose you this little word just to say thanks a lot as before for your personal remarkable knowledge you\\\'ve shared on this page. This is quite surprisingly generous with people like you to grant unhampered what most of us would\\\'ve distributed as an electronic book to help with making some money for their own end, most importantly seeing that you could have tried it in case you decided. The things likewise worked as the easy way to realize that someone else have the same dream much like mine to understand more and more when considering this matter. I\\\'m sure there are millions of more fun periods up front for individuals that look into your blog post.

SearchEngineOptimization