Running on Empty

The few things I know, I like to share.

WPF EnumComboBox UserControl

Introduction

In this article I will demonstrate a custom control that will allow you to display items from an enum in a combo box.  I have a couple of requirements though.

  • The displayed values must be in human readable strings, numbers or the enum type would not do.
  • The implementation must be easily reusable.

Creating the EnumComboBox Control

First, create a class that will allow us to view the description of custom attributes.

public class EnumerateUtil
{
    // Methods
    private EnumerateUtil()
    {
    }

    public static string GetDescription(Enum value)
    {
        DescriptionAttribute[] customAttributes = (DescriptionAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
        return ((customAttributes.Length > 0) ? customAttributes[0].Description : value.ToString());
    }
}

Next, create a new custom control, I called mine EnumComboBox.

public class EnumComboBox : System.Windows.Controls.ComboBox
{
    static EnumComboBox()
    {
       
        //This OverrideMetadata call tells the system that this element wants to provide a style that is different than its base class.
        //This style is defined in themes\generic.xaml
        //DefaultStyleKeyProperty.OverrideMetadata(typeof(EnumComboBox), new FrameworkPropertyMetadata(typeof(EnumComboBox)));
    }

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);
        FillItems();       
    }

    private string _enumType;
    [Browsable(true), Category("Data"), Description("Sets the fully qualified type of the enum to display in the DropDownList")]
    public string EnumTypeName
    {
        get { return _enumType; }
        set { _enumType = value; }
    }

    private List<KeyValuePair<int, string>> CachedValues
    {
        get
        {
            if (App.Current != null && App.Current.Properties != null)
            {
                return (List<KeyValuePair<int, string>>)App.Current.Properties["EnumComboBox_" + EnumTypeName];
            }
            else
            {
                return null;
            }
        }
        set
        {
            if (App.Current != null && App.Current.Properties != null)
            {
                App.Current.Properties["EnumComboBox_" + EnumTypeName] = value;
            }
        }
    }

    private void FillItems()
    {
        List<KeyValuePair<int, string>> values = CachedValues;
        if (values == null)
        {
            values = new List<KeyValuePair<int, string>>();
            Type enumType = Type.GetType(EnumTypeName);
            if (enumType == null)
            {
                throw new ArgumentException("Cannot load the type: " + EnumTypeName);
            }
            Array enumValues = Enum.GetValues(enumType);
            for (int index = 0; index < enumValues.Length; index++)
            {
                int value = (int)enumValues.GetValue(index);
                Enum enumValue = (Enum)enumValues.GetValue(index);
                values.Add(new KeyValuePair<int, string>(value, EnumerateUtil.GetDescription(enumValue)));
            }
            CachedValues = values;
        }

        this.ItemsSource = values;
        this.DisplayMemberPath = "Value";
        this.SelectedValuePath = "Key";
    }
}

Note, I commented the OverrideMetadata style property in the constructor.  This is because, I want to apply my template on a control by control basis.Finally, create your enum and use description attributes to specify the visible string.

public enum TestType
{
    [Description("Object One"), EnumMember]
    ObjectOne = 1
   ,
    [Description("Object Two"), EnumMember]
    ObjectTwo = 2
}

 


Declaring the EnumComboBox

Now all we need to do is point the EnumTypeName property to the Entity that we will use to fill the combo box values.

<customControls:EnumComboBox EnumTypeName="YourNamespace.TestType, YourNamespace"/>

 


Conclusion

In this article I demonstrated using Description attributes and custom controls to create a combobox that will fill with human readable strings.  Hopefully you found this useful.

Please feel free to leave comments or suggestions.

Advertisements

January 15, 2008 Posted by | C#, WPF, XAML | 3 Comments