Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Enum to ComboBox binding

0.00/5 (No votes)
7 May 2013 3  
This tip gives a simple way to bind enum values into a ComboBox that could be reused in different applications.

Introduction

Any real world application would like to bind Enum values to a ComboBox. So it is always better to have a common code that will do the logic.

Using the Code

I have a helper class which exposes a property to get the enum type so that I can resolve the enum values.

public static Type GetEnum(DependencyObject obj)
{
    return (Type)obj.GetValue(EnumProperty);
}
public static void SetEnum(DependencyObject obj, string value)
{
    obj.SetValue(EnumProperty, value);
}
// Using a DependencyProperty as the backing store for Enum.  
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty EnumProperty =
    DependencyProperty.RegisterAttached("Enum", typeof(Type), 
    typeof(EnumHelper), new PropertyMetadata(null, OnEnumChanged));  

Get the values of the enum and set it as ComboBox ItemsSource.

private static void OnEnumChanged(DependencyObject sender, 
                          DependencyPropertyChangedEventArgs e)
{
    var control = sender as ItemsControl;
    if (control != null)
    {
        if (e.NewValue != null)
        {
            var _enum = Enum.GetValues(e.NewValue as Type);
            control.ItemsSource = _enum;
        }
    }
}

Now the ComboBox will bind to the enum values, if we set the enum value in XAML.

public enum Designation
{
   SoftwareEngineer,
   TeamLead,
   ProductManager
} 
<ComboBox x:Name="Designation" Margin="5" Grid.Row="5"
      SelectedItem="{Binding Designation, Mode=TwoWay}"
      local:EnumHelper.Enum="{x:Type local:Designation}">
</ComboBox>   

Look at the names of items. They are not well spaced. It should be Product Manager instead of ProductManager. For this, we will use the Display attribute of enum values. Further, we can also use the Description attribute to let the user see more details.

I have modified my enum to look like below:

public enum Designation
{
    [Display(Name="Software Engineer")]
    [Description("Software engineer responsible for core development.")]
    SoftwareEngineer,
    [Display(Name = "Team Lead")]
    [Description("Team lead responsible for leading a small team of 5 to 10 members.")]
    TeamLead,
    [Display(Name = "Product Manager")]
    [Description("Product manager responsible for core management.")]
    ProductManager
}  

Also our helper class should expose another property to get the values of attributes and set it wherever needed. For example, in this case I will show the description as a tooltip and display as text.

public static bool GetMoreDetails(DependencyObject obj)
{
    return (bool)obj.GetValue(MoreDetailsProperty);
}
public static void SetMoreDetails(DependencyObject obj, bool value)
{
    obj.SetValue(MoreDetailsProperty, value);
}
// Using a DependencyProperty as the backing store for MoreDetails.  
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty MoreDetailsProperty =
    DependencyProperty.RegisterAttached("MoreDetails", 
    typeof(bool), typeof(EnumHelper), new PropertyMetadata(false, OnMoreDetailsChanged)); 

We are getting the attribute values and set it in the appropriate places. We expect the user to set this property in any DataTemplate so that we can get the underlying enum object as a DataContext.

var array = fieldInfo.GetCustomAttributes(false);
if (array.Length == 0)
{
    if (control is TextBlock)
    {
        ((TextBlock)control).Text = enumobject.ToString();
    }
    else if (control is ContentControl)
    {
        ((ContentControl)control).Content = enumobject;
    }
    return;
}
foreach (var o in array)
{
    if (o is DescriptionAttribute)
    {
        control.ToolTip = ((DescriptionAttribute) o).Description;
    }
    else if (o is DisplayAttribute)
    {
        if (control is TextBlock)
        {
            ((TextBlock) control).Text = ((DisplayAttribute) o).Name;
        }
        else if (control is ContentControl)
        {
            ((ContentControl)control).Content = ((DisplayAttribute)o).Name;
        }
    }
}  

Let's add a DataTemplate to the ComboBox:

<DataTemplate>
    <TextBlock local:EnumHelper.MoreDetails="True"/>
</DataTemplate>   

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here