Binding a Combobox to an Enum in C# and WPF using XAML and MVVM
I saw a lot of posts on how to bind an enum to a combobox using code behind and C#, but since I was using MVVM, I needed a different solution. I basically wanted to bind a list of the enums in a maintenance view model, and have the the xaml handle the binding of the item list. To help remember what I did and help whomever along the way with the same issue, I thought I would write about it.
Let’s start off with a basic enumeration :
public enum VolumeLevel { [Description("Low")] LowVolume = 1, [Description("Medium")] MediumVolume = 3, [Description("High")] HighVolume = 5 }
Now make that enumeration into a collection in your maintenance view model (or where ever you bind the lists on your comboboxes, etc…). There are a few ways to do this, I just replicated what I’ve done with other collections, just with a little twist to get the descriptions.
private List<keyvaluepair<string,<span class="hiddenSpellError">VolumeLevel>> _VolumeLevelList; public List<keyvaluepair<string,<span class="hiddenSpellError">VolumeLevel>> VolumeLevelList { get { if (_VolumeLevelList == null) { _VolumeLevelList = new List<KeyValuePair<string, VolumeLevel>>(); foreach (VolumeLevel level in Enum.GetValues(typeof(VolumeLevel))) { string Description; FieldInfo fieldInfo = level.GetType().GetField(level.ToString()); DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false); if (attributes != null && attributes.Length > 0) { Description = attributes[0].Description; } else { Description = string.Empty; } KeyValuePair<string, volumelevel=""> TypeKeyValue = new KeyValuePair<string, VolumeLevel>(Description, level); _VolumeLevelList.Add(TypeKeyValue); } } return _VolumeLevelList; } }
So now that you have your list and your enumeration, let’s insert the final piece. This will be the combobox in the xaml with bindings to your List. Note : The form I am using is a child of a maintenance view, so if your enum list is within the current datacontext, you won’t need the relative source binding.
<ComboBox Height="23" Width="125" HorizontalAlignment="Left" DisplayMemberPath="Key" SelectedValuePath="Value" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type my:VolumeChangerMaintenanceView}}, Path=DataContext.VolumeLevelList}" SelectedValue="{Binding SelectedVolumeLevel, ValidatesOnDataErrors=True, Mode=TwoWay}" />
There you go. All wired up and good to go. There are a few different ways to do this, but I thought I’d share mine just in case it helps somebody. Happy coding!
** UPDATE 11/16/2012 **
George had asked for a working example. I noticed an error in my code and is now fixed. Here is the working example!
**UPDATE 1/9/2014**
There was an issue with not calling the raise property changed from the public property, code has been updated and fixed
Hi,
could you attach working example for this?
There is now a working example attached at the bottom of the post.
Wonderful! This is the first example that has worked for me. I’ve been on this issue for a few days now, and whoever designed ComboBox should be punished.