Introduction

As .NET developers, we know about and have probably used Enums before. For those that haven't used enums before, this is what MSDN has to say about them:

"The enum keyword is used to declare an enumeration, a distinct type consisting of a set of named constants called the enumerator list. Every enumeration type has an underlying type, which can be any integral type except char."

So when we use enums, we can actually do things like

enum Hardware {DiskDrive=1, Keyboard, GraphicsCard, Monitor};

Now this is all well and good, but imagine if we wanted to display a list of enums within a list, and we actually wanted to have more descriptive values, friendly names if you like, but still maintain the underlying enum value selected where required.

This article will show you how to do the following, using WPF:

Bind to a Enumeration of enum values

Display friendly names for enums, to aid the user experience

Bind to a Enumeration of Enum Values

The first thing that we might want to do is display a list of all possible enum values, such that a current value may be selected within this list, or allow the user to select a new enum value. This is easily achievable using the following technique:

Where I have a demo enum declared as follows (if you could just ignore the LocalizableDescriptionAttribute for the moment, more on that later) :

publicenum FoodTypes : int
{
Pizza = 1,
Burger = 2,
SpagBol = 3
}

This will result in the following:

Display Friendly Names for Enums, to Aid the User Experience

Now this does half the job, but from a users' point of view, some more descriptive text may actually aid the user experience, so what can we do about that. Well as luck would have it, Reflection and Attributes have the answer. We are able to adorn our enum with a special attribute namely a derived LocalizableDescriptionAttribute which inherits from DescriptionAttribute, which may be used as follows:

I should point out that the original content of this article used the EnumMember which as several readers noted could not be localized for different cultures. Luckily one of those readers was the ultra talented Uwe Keim, who gave me some code for handling the localization of enums. This code is shown below for the LocalizableDescriptionAttribute. Thanks Uwe.

The basic idea here is that this LocalizableDescriptionAttribute allows you to pass in a key and a resource type to look at, so the key value will index into the resource file and get the value of the resource file. This is shown below in the small resource file that is part of the demo code attached.

So now that we know we can do this with the enums, what about using this as a ComboBox within the XAML. Mmmm, well luckily there is another WPF trick we can use to aid here, which is IValueConverter. Let's see the revised XAML:

The actual magic happens by the use of some Reflection. So if you need to run this in an XBAP, you will need to make sure it is run in FullTrust mode.

The final step of the puzzle is to make sure that the selected value makes its way back into the source object that may use one of the enum values. I am using a simple test setup comprised of a single ViewModel and a single test class. This should be obvious from the attached demo code.

Anyway, the part that ensures the test class receives the actual enum value, and not the friendly name, which it would not know what to do with, is a simple case of more databinding in the XAML. This is as follows:

Where this now includes a binding to the SelectedItem, which is a TwoWay binding to the actual enum value within the test class.

So putting it all together, we now have a bound ComboBox which shows friendly values to the user, but maintains the correct enum values within the bound object, for the selected item.

And here is the test classes selected value, notice that it is the correct enum value:

I think this aids the user experience, a bit, hope it helps you out, as it has me.

Alternative Approach

Since I wrote this article, the legendary Andrew Smith (Infragistics....(Josh Smith even calls him a guru)), sent me an email with an alternative approach where he creates a MarkupExtension that does that same as this, so you might like to check out that at Andrews blog. The post is available using the link, http://agsmith.wordpress.com/2008/09/19/accessing-enum-members-in-xaml/, thanks Andrew.

awesome article you wrote there it really helped me a lot. There is one little thing though. If i use this data template my Comboboxes become really large it looks like there is a margin around the dataTemplate even though the labels margin is set to 0. is there any way to get rid of this ? really messes up the GUI

EDIT: You have to set Padding="0" in the Data Template to get rid of this effect

Although I found the article really useful, I must be honest and say that I dont really like any of implementations as they seem overtly complicated when binding an Enum to a ComboBox. Hence I have some questions.

This kindof works, as I have a nested enum[^] inside MyClass,however it makes the designer to crumble in design mode but It works in the release, and seems to have been an Issue since 2006:MSDN[^]However the documentation seems to Ignore this possibility:MSDN documentation[^]This is indeed my first question, It should work if I put the Enum inside a Namespace and reffer to this in the XAML right? (I couldnt make this work properly, so perhaps I forgot something?)

I also found a solution that uses a ValueConverter[^], but the one solution that I could not find is one that used some kind of attached property as Bea Stollnitz[^] used to create a internal drag drop that changes the index. Is it not possible to create a simular attached property called EnumItemsSource or simular and just attach it to the ComboBox? And what will I have to do in order to achieve this or is it not possible?

Unfortunately I personally found the code unusable due to the lack of namespace definitions. I assume the x is the default notation defined by visual studio when a new window is created (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml") but I couldn't figure out what sys and local are supposed to be. I assume I am doing something very wrong somewhere, because even x does not work properly (for example I don't seem to have any x:key attribute for the ObjectDataProvider), but I am at a loss to figure out what I am missing.

Again you wrote a great article on a WPF topic.I played with the sample project, added an enum from another namespace/dll, and it was very simple to get it working.While doing so, I found that I have to repeat too many things, e.g.

[LocalizableDescription(@"Pizza", typeof(Resource))]
Pizza = 1,

the name of the enum value ("Pizza") is repeated, and for every enum value I have to set the same Resource (it does not make sense to use different resources for an enumeration). How could the LocalizableDescription attribute figure out that automagically? I'd prefer to set the resource as an attribute for the whole enumeration. In an enum description converter which I use outside WPF, I determine the key for the resource by

I do not know how to integrate that into the LocalizableDescription's constructor.Also I wonder whether the ObjectDataProvider could be made more generic, it uses so many lines where only the name of the enum and the new name of the static resource differ.Thanks a lot for your hints.

HI, I see that you didn't implement ConvertBack method. What if I need to update entity property based on user selected enum value? if I set Mode=TwoWay, I will get a localized string passed to value parameter in ConvertBack method. How to get the enum property from selected value which is localized?

I was able to make it working by using a wrapper class with Member and Description properties, and binding to array of wrapper type instead off array of objects, but I am not sure if I am missing something obvious.

Its been a while since I wrote this, but I have just run it again, and it just works how you want it to anyway.

If you run it (as is in the download code) you will see a messagebox with the current RAW enum value being shown, which is the result of the SelectedItem (which is 2 way), binding to the enum get/set in the ViewModels TestClass property

Is it possible to do this using attributes (not DescriptionAttribute though), but on the enum level? If we assume that we would use the same resource file for all enum members, and if we assume that we would not need to add description, but use enum member as key in resource file, then a general attribute that would accept a resource type would do the trick.

If this is possible, what type of attribute would be most suitable for this purpose, and can you write a very quick explanation what steps are involved to achieve this? I know you guys are busy so I don't ask for detailed guidance.

Yeah I think this probably would be possible. Have not fully thought it out but here is how I think it could work

1. In the value converter call a static helper method passing in the enum type and current value2. For each attribute value have a resource string which is of the form : EnumType_EnumValue

So we would have something like this in resources file

Name FoodTypes_PizzaFoodTypes_BurgerFoodTypes_SpagBol

where values are the actual text.

3. The static helper method should take in enum type and enum current value, and build resource lookup string like string.Format("{0}_{1}",enumType,enumCurrentValue). This formatting string could then be used to look up the resource value from the resource file like it currently does in current codes LocalizableDescriptionAttribute.Description property

HI, thanks for quick response. Yes this is how I thought of using it. The only problem that I am confused with is how to pass the resource type we are using? In DescriptionAtrtibute you are passing it to the constructor for each member of enum. How to do this on the enum level?

Or to be precize, what kind of attribute is best to use for this purpose? I can do this by inheriting from basic Atrribute class, but I am not sure if this is the correct way?

Ah yes good point so in that case just use some custom attribute which can acceptresource type in attribute constructor, or have a lookup dictionary somewhere where you can get resource for enum type, and then pass resource type to helper method along with attribute type and attribute current value.

Thanks for the excellent article! I found out how you can do the localization of the description even easier. If it's ok to have public resources (standard is internal) you can also use this following code for localized descriptions. In the constructor the property info gets stored. The info is later used for getting the value of the resource. With this version you can also switch UI Culture at runtime.

I successfully implemented your Friendly Enums in a WPF project.Thank you so far.

Let me describe my current situation:

In my WPF project I have two windows. In the first is the Friendly Enum with combobox display. Then I go to the second window with some information displayed on it. There is the possiblity to go back to the first screen. When I go back to the first screen, the information entered in the combobox is reset to its original state. I would like to have the changed state of the combobox persistent:Is it possible, and how is it possible, to save the state of the combobox between the two windows?

Please do ask, if I can supply more information, and be elaborate in you post, because I am new to WPF.