Click here to Skip to main content
12,299,440 members (55,758 online)
Click here to Skip to main content
Add your own
alternative version


19 bookmarked

Using DescriptionAttribute for enumerations bound to a WPF ComboBox

, 27 Jan 2016 CPOL
Rate this:
Please Sign up or sign in to vote.
How to use DescriptionAttribute for enumerations bound to a ComboBox.


A great maintenance headache is maintaining the View with changes in enumerations, and also just making sure that the enumeration is associated with the right item in a ComboBox (possibly a ListBox).


I have thought about how to deal with this problem for a while. I was considering ways of using the name for each item in the enumeration as the associated name in the UI. If I did this, I could use the enumeration type as the ItemSource for the ComboBox, and then translate the string back to the enumeration. The problem is that sometimes you want to have spaces in the View to the user (besides the issue that the name for the enumeration states may not be what should be displayed). I thought of two possibilities, using underlines in the enumeration names and translating them to spaces using a value converter, or using a value converter to insert a space in front of each capital letter. Then I found out that I can associate a description to each enumeration value using the DescriptionAttribute. It is then possible to get to this description string, and then it is possible get an enumeration of descriptions to use as an item source, and to convert an enumeration value to its description and convert a description to the associated enumeration.


The example that I have created for this paper is very simple. It consists of a ComboBox that has the enumeration descriptions as the ComboItems.

The first thing that is needed is the enumeration with a description for each enumeration. I created something very basic for this example:

public enum SampleEnum
     [DescriptionAttribute("I like the color blue")]
     [DescriptionAttribute("I like the color green")]
     [DescriptionAttribute("I like the color yellow")]
     [DescriptionAttribute("I like the color red")]

One of the enumerations does not have a DescriptionAttribute so I can show that the code handles this situation.

Now that we have the enumeration, we need two value converters, one to convert an enumeration value to a description and another for description to an enumeration. There is no need to have a different value converter for each enumeration since the enumeration type is available to the value converter. The implementation of this converter is as follows:

class EnumDescriptionConverter : IValueConverter
  private class LocalDictionaries
    public readonly Dictionary<int, string> EnumDescriptions = 
        new Dictionary<int, string>();
    public readonly Dictionary<string, int> EnumIntValues = 
        new Dictionary<string, int>();
  private readonly Dictionary<Type, LocalDictionaries> _localDictionaries =
    new Dictionary<Type, LocalDictionaries>();
  public object Convert(object value, Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
    if (value == null || !value.GetType().IsEnum)
      return value;
    if (!_localDictionaries.ContainsKey(value.GetType()))
    return _localDictionaries[value.GetType()].EnumDescriptions[(int)value];
  public object ConvertBack(object value, Type targetType,
    object parameter, System.Globalization.CultureInfo culture)
    if (value == null || !targetType.IsEnum)
      return value;
    if (!_localDictionaries.ContainsKey(targetType))
    int enumInt = _localDictionaries[targetType].EnumIntValues[value.ToString()];
    return Enum.ToObject(targetType, enumInt);
  private void CreateDictionaries(Type e)
    var dictionaries = new LocalDictionaries();
    foreach (var value in Enum.GetValues(e))
      FieldInfo info = value.GetType().GetField(value.ToString());
      var valueDescription = (DescriptionAttribute[])info.GetCustomAttributes
        (typeof(DescriptionAttribute), false);
      if (valueDescription.Length == 1)
      else //Use the value for display if not concrete result
        dictionaries.EnumDescriptions.Add((int)value, value.ToString());
        dictionaries.EnumIntValues.Add(value.ToString(), (int)value);
    _localDictionaries.Add(e, dictionaries);

When converting the enumeration to the description, there is first a check that the type is an enumeration since there is no point in continuing otherwise (for the Convert method, the type of the value argument is checked, and for ConvertBack, the targetType argument is checked). Then there is a check that the two dictionaries needed to convert to/from a description string have been initialized, and if not, calls the method to create the two dictionaries.

It is this CreateDictionaries method where the magic happens. Here, the FieldInfo for each enumeration is interrogated for a DescriptionAttribute. If this attribute exists, then the value is associated with the enumeration in both dictionaries, otherwise the ToString() value of the enumeration is used. With the two dictionaries created, it is now possible to look up the description using the integer value of the enumeration, or look up the integer value of the enumeration using the description, making it quick to convert between the two for the Convert and ConvertBack methods. Probably unnecessary to do the check for the dictionaries to be initialize in the method, but the converter may be used in some unusual way, so I do not consider it back to add a simple check. Now everything is in place to return the description or enumeration value as there is no issue with converting the enumeration either from (for the ConvertBack once the dictionary lookup has been done) or to (for the Convert, the value argument being converted before using the dictionary) an Integer. Using an integer for the dictionaries instead of the enumeration lets the dictionaries work without the converter being customized to a specific enumeration type.

Note that a dictionary is used to save the two translation dictionaries. The key for this dictionary is the type. This is because the same instance of the converter is used for all conversions. This would not be a problem with the example, but if I had a second enumeration ComboBox using a different enumeration, there would be a problem. It would be an option to go through all the enumeration values each time, but I believe that that would have a performance impact, so it makes more sense to maintain the information for all the enumeration types, paying the small penalty for the lookup. Also note that a class is used for the dictionary pair.

A separate, but much simpler converter is used for the ItemSource converter. It is simpler because there is no need to code the ConvertBack method, and only a list of descriptions needs to be created: 

    public class EnumDescriptionSourceConverter : MarkupExtension, IValueConverter
        private readonly Dictionary<Type, List<string>> _localLists =
          new Dictionary<Type, List<string>>();

        public object Convert(object value, Type targetType, object parameter,
          System.Globalization.CultureInfo culture)
            if (value == null || !value.GetType().IsEnum)
                return value;
            if (!_localLists.ContainsKey(value.GetType()))
            return _localLists[value.GetType()];

        public object ConvertBack(object value, Type targetType, object parameter,
          System.Globalization.CultureInfo culture)
            throw new NotImplementedException("There is no backward conversion");

        private void CreateList(Type e)
            var list = (from object value in Enum.GetValues(e)
                        let info = value.GetType().GetField(value.ToString())
                        let valueDescription = (DescriptionAttribute[])info.
				GetCustomAttributes(typeof(DescriptionAttribute), false)
                        select valueDescription.Length == 1 ? valueDescription[0].Description 
				: value.ToString()).ToList();
            _localLists.Add(e, list);

        public override object ProvideValue(IServiceProvider serviceProvider)
            return this;

Note: it is possible to get by with one value converter by checking the target type, and return a collection of descriptions if the type is IEnumerable.

With the converters and the enumeration, it is very straightforward to create the XAML to create a more maintainable ComboBox for enumerations:

<Window x:Class="EnumComboBoxBindingWithDescExample.MainWindow"
    xmlns="<a href=""></a>"
    xmlns:x="<a href=""></a>"
    Title="Enum Description ComboBox Example" Height="200" Width="300">
  <SolidColorBrush Color="{Binding Text,ElementName=SelectedColor}"/>

Note: the figure is not the same XAML as above. It is similar, but adds some decoration, including a TextBox to show the actual enumeration value of the item selected in the ComboBox, and that TextBox is bound to the Background of the window (a nice feature is that directly binding to the ViewModel value will not work because only after it is translated into text will it actually specify a color).


With simply two value converters and the use of the DescriptionAttribute when defining an enumeration, it is possible create a ComboBox for selecting options defined by the enumeration, with the DescriptionAttribute argument specifying the text for the ComboBoxItems; no need to specify ComboBoxItems in the XAML. This enhances maintainability, removing the need to coordinate changes in the enumeration with the UI, and allows defining the enumerations and the text associated with the enumerations in one place. There is also the advantage that if an enumeration is used with a ComboBox in more than one place, we still have the ComboBoxItem.Text in one place without having to add to the ViewModel, or add a static variable somewhere, and the associated text is with the enumeration instead of being hidden in a ViewModel or a static variable.

The one drawback to this concept that I know of is internationalization. There is also the issue that when space is available, it is preferred to use radio buttons to a ComboBox since it is quicker for the user with less steps and the options are readily obvious. We can still use value converters, but a little more work is required to setup a ListBox to display RadioButtons.


November 14, 2011: Made a mistake in thinking that could not have a dictionary of List when Visual Studio complained about a second “>” in “Dictionary<Type, List<string>>”. This error was pointed out by Reto Ravasio and I wish to thank him for the correction. I have changed the code for the converter used to return an enumeration of descriptions to use a dictionary of Lists and fixed the article appropriately.

September 30 2015: Updated code to handle nullable enumerations, and fixed some issues with the layout.

January 27, 2016: Created new version that only has one converter, using the same converter for binding both the ItemsSource and the SelectedItem. Thus when binding, the same converter is used:

<ComboBox ItemsSource="{Binding LensType,
          SelectedItem="{Binding LensType,
                                 UpdateSourceTrigger=PropertyChanged}" />

March 10 2016: Fixed bug in EnumBindingConverter.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Clifford Nelson
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with Clarity Medical in Pleasanton, CA redesigning their UI for their camera system. he can be reached at

You may also be interested in...

Comments and Discussions

SuggestionTag as WPF Pin
RickZeeland23-Mar-16 5:32
professionalRickZeeland23-Mar-16 5:32 
AnswerRe: Tag as WPF Pin
Clifford Nelson23-Mar-16 10:00
memberClifford Nelson23-Mar-16 10:00 
QuestionGuess there are more elegant ways! Pin
vallarasus20-Nov-11 7:50
membervallarasus20-Nov-11 7:50 
QuestionThoughts Pin
PIEBALDconsult16-Nov-11 7:50
memberPIEBALDconsult16-Nov-11 7:50 
AnswerRe: Thoughts Pin
Clifford Nelson16-Nov-11 9:02
memberClifford Nelson16-Nov-11 9:02 
QuestionSimilar Pin
Collin Jasnoch11-Nov-11 10:18
memberCollin Jasnoch11-Nov-11 10:18 
AnswerRe: Similar Pin
Clifford Nelson14-Nov-11 9:37
memberClifford Nelson14-Nov-11 9:37 
GeneralRe: Similar Pin
Collin Jasnoch14-Nov-11 10:05
memberCollin Jasnoch14-Nov-11 10:05 
GeneralRe: Similar Pin
Clifford Nelson14-Nov-11 12:20
memberClifford Nelson14-Nov-11 12:20 
SuggestionStrange Way Pin
Reto Ravasio10-Nov-11 14:14
memberReto Ravasio10-Nov-11 14:14 
GeneralRe: Strange Way Pin
Clifford Nelson11-Nov-11 9:59
memberClifford Nelson11-Nov-11 9:59 
AnswerRe: Strange Way Pin
Reto Ravasio11-Nov-11 15:54
memberReto Ravasio11-Nov-11 15:54 
GeneralRe: Strange Way Pin
Clifford Nelson14-Nov-11 9:23
memberClifford Nelson14-Nov-11 9:23 
GeneralRe: Strange Way Pin
Reto Ravasio15-Nov-11 6:30
memberReto Ravasio15-Nov-11 6:30 
GeneralRe: Strange Way Pin
Clifford Nelson20-Nov-11 14:31
memberClifford Nelson20-Nov-11 14:31 
GeneralNice and to the point article Pin
RabinDl10-Nov-11 9:18
memberRabinDl10-Nov-11 9:18 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.160525.2 | Last Updated 27 Jan 2016
Article Copyright 2011 by Clifford Nelson
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid