Click here to Skip to main content
15,889,200 members
Articles / Desktop Programming / WPF
Tip/Trick

Very Friendly Enum Binding In WPF

Rate me:
Please Sign up or sign in to vote.
5.00/5 (10 votes)
11 Jan 2016CPOL3 min read 27.7K   13   8
A super simple method for listing Enum members in WPF using databinding

Introduction

Providing users a selectable list of an enumeration in a UI is common sense, when you need your users to select an element of predefined qualities. However, the enumeration has to be displayed in a user friendly way. It turns out, there's a very simple way to do this, without using any custom methods, reflection, value converters, data templates or what not.

Background

I'm only a beginner in C#, and when I need any kind of functionality, I turn to CodeProject to see what the masters advise. When I needed a friendly way to list an enumeration, I came across Sacha Barber's article on CodeProject. Since I'm mainly a JavaScript programmer and just a beginner to both C# and WPF, the amount of code just needed to show a simple list seemed way too much, and frankly I didn't understand half of the code! The alternative method linked in his article didn't fare better.

Using the Code

To list any kind of user selectable enumeration in your UI, in a user friendly way, there are only, and only 4 simple steps:

  1. Define your enum normally as you would in a public class.
  2. Prepare a dictionary with your enum members as key and their descriptions as value.  Note: In the value part, you can point to strings in your .resx file if you are planning on translations, just as you would do for any string that needs to be translated.
  3. Expose the dictionary and an enum selection in your view model for consumption by your UI.
  4. Bind to your dictionary in your XAML in a combobox, display just the value, and select just the keys.

I frankly have no idea why it has to be any more complex than this. Here's step 1 and 2:

C#
public static class Definitions
{
  public enum nation
    {
      tr, fr, us, gb, gr
    }

public static Dictionary<nation, string> NationEnumDictionary = new Dictionary<nation, string>()
    {
      { nation.tr , "Turkish" },
      { nation.fr , "French" },
      { nation.us , "US citizen" },
      { nation.gb , "British" },
      { nation.gr , "Greek" }
    };
}

Here's step 3, in your view model:

C#
public Dictionary<Definitions.nation, string> NationalityList
{
  get { return Definitions.NationEnumDictionary; }
}

public Definitions.nation SelectedNationality { get; set;}

And here's step 4, in your XAML code:

XML
<ComboBox ItemsSource="{Binding NationalityList}" DisplayMemberPath="Value" 
SelectedValuePath="Key" SelectedValue="{Binding SelectedNationality}" 
Height="22" Width="80" />

The result is a combobox which lists your enumeration in a user friendly way, yet allows you to have the selection work as an enum member:

How It Works

ComboBox and other element selectors in WPF allow you to display an item's property (DisplayMemberPath), while having the selection point to another property on the object (SelectedValuePath) in addition to the SelectedItem, which happens to be a KeyValuePair for a dictionary item. Setting these appropriately will allow you to create versatile lists.

Points of Interest

  • The very simple nature of this technique allows you to provide multiple dictionaries for a single enumeration, as the enum member could mean something slightly different in different parts of the UI
  • It should also play well with localization. Instead of writing the strings in the dictionary, point to your strings in the .resx file in value part the dictionary. You don't even have to change the member types in the dictionary, as the .resx data is still a string.
  • Different dictionaries can be served to the UI based on different conditions.
    • You do not need to expose all of the enumeration list, only the part you need. For example, you can have a gender.indeterminate enum member in your gender enumeration as a fallback value, but you may choose to only show the descriptions for gender.male or gender.female in your UI. This provides versatility, you don't have to redefine different enumerations or have "do not list" properties per item if the enum member does not have to be listed.

Of note, this dictionary "trick" is not confined to enumerations. For any given list of C# built-in data type, you can display a custom list of user friendly strings. The user friendly strings do not have to be in the value part, but they can be the keys in the dictionary too. You'll just need to tell in your XAML which part of the dictionary items will be displayed (the Key, or Value part), and which part of the dictionary will be selected (its Value or Key part, respectively), e.g. you can have the users select "One grand", and the selected value can be 1000 as an integer.

License

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


Written By
Web Developer
Turkey Turkey
I'm a hobbyist programmer, with considerable experience for HTML, CSS, and Javascript, and only just getting into C# out of necessity to help solve a few problems at work (late 2015)

Comments and Discussions

 
SuggestionInteresting Pin
Imagiv19-Jul-16 2:36
Imagiv19-Jul-16 2:36 
Interesting to see this, but in my opinion, I feel like it's a bit much. I've always said it'd be nice if we could just bind the enum value we want to the ComboBox and be done with it.

Here's a converter I use that takes any enum type or enum type value and converts it to a bindable collection.
[ValueConversion(typeof(Enum), typeof(ObservableCollection<Enum>))]
public class EnumToCollectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return null;
        Type Type;
        if (value is Enum)
            Type = value.GetType();
        else if (value is Type)
        {
            Type = (Type)value;
        }
        else
            return null;
        ObservableCollection<Enum> Items = new ObservableCollection<Enum>();
        System.Array EnumValues = Enum.GetValues(Type);
        foreach (object Value in EnumValues)
            Items.Add(Value as Enum);
        return Items;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


And you'd simply use it like this:
<ComboBox ItemsSource="{Binding Source={x:Type YourNamespace:YourEnum}, Converter={StaticResource EnumToCollectionConverter}}" SelectedValue="{Binding YourViewmodelEnumValue, Mode=TwoWay}"/>


And then if you wanted integers instead of enum values, you could specify a converter parameter (not in example) and it would store just the integers.

OR, instead of returning an ObservableCollection of integers or enum values, you could return one of a dictionary that contains both the integer and the enum value.

Not sure what the advantages are specifically of doing it your way versus mine, but I feel this way is simpler. On a related note, I bind to RadioButtons almost identically so I have nothing to fuss about there.

At any rate, good article!

EDIT:

Just wanted to add a comment about using description attributes because I saw someone else mention it. This is, indeed, another viable solution, one which can be resolved with just one line:

Enumerations.GetEnumDescription((MyEnum)value);


So if one wishes to get the label for the enum value from a description attribute, that's how it's done.
GeneralRe: Interesting Pin
hesido27-Sep-16 2:25
hesido27-Sep-16 2:25 
SuggestionClean up notations in code. Pin
Hein Pauwelyn13-Jan-16 22:23
Hein Pauwelyn13-Jan-16 22:23 
GeneralRe: Clean up notations in code. Pin
hesido14-Jan-16 1:18
hesido14-Jan-16 1:18 
AnswerBetter solution Pin
Clifford Nelson2-Jan-16 18:02
Clifford Nelson2-Jan-16 18:02 
GeneralRe: Better solution Pin
hesido3-Jan-16 21:11
hesido3-Jan-16 21:11 
GeneralRe: Better solution Pin
Chinatablet4-Jan-16 17:17
professionalChinatablet4-Jan-16 17:17 
GeneralRe: Better solution Pin
hesido26-Mar-16 1:04
hesido26-Mar-16 1:04 

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.