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:
- Define your
enum
normally as you would in a public
class.
- 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.
- Expose the
dictionary
and an enum
selection in your view model for consumption by your UI.
- 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:
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:
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:
<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.