65.9K
CodeProject 正在变化。 阅读更多。
Home

将枚举值绑定到 ComboBox

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (5投票s)

2015年3月15日

CPOL

1分钟阅读

viewsIcon

19468

downloadIcon

159

一种简洁通用的解决方案,用于将枚举(带或不带 DescriptionAttribute)绑定到 ComboBox 或其他控件

引言

这里提供的解决方案提供了一种简单而简洁的方法,可以将 Enum 绑定到 ComboBox,或者(只需进行少量调整)绑定到任何其他可绑定的控件。 如果您使用 DescriptionAttribute 装饰了您的 Enum 成员,则可以使用该描述作为控件绑定的 DisplayMember,否则可以使用 Enum 成员的名称代替。

背景

这个技巧的想法源于我对 CodeProject Q&A 中最近一个问题的回答,在评论中有人建议我将其写成一个技巧。 Q&A 提问者在 Code Review (StackExchange) 上的一个问题 中遇到了一个提出的解决方案的实现问题(尤其是 StackExchange 成员 Jesse C. Slicer)。 我只声称对使其成为一个通用解决方案(以及进行一些其他小的改进)并将其打包成一个简洁的示例负责。

Using the Code

该示例使用了这两个 Enum 定义 - 一个带有 Description 属性,一个没有。

public enum AnimalOption
{
    [Description("flying animal")]
    Bird,
    [Description("best friend")]
    Dog,
    [Description("cuddly carnivore")]
    Cat
}

public enum ShapeOption
{
    Circle,
    Rectangle,
    Line
}

它们在 Form 的构造函数中绑定到 ComboBox。 如您所见,它是通过一个泛型扩展方法到 ComboBox 完成的,该方法将 Enum 类型作为泛型类型参数,并带有一个 DisplayMode 参数,该参数指示它是否应该查找 Description 属性以用于 DisplayMember,或者使用 Enum 成员的名称代替(ValueToString)。

public Form1()
{
    InitializeComponent();

    AnimalComboBox.BindEnum<AnimalOption>(DisplayMode.DescriptionAttribute);
    ShapeComboBox.BindEnum<ShapeOption>(DisplayMode.ValueToString);
}

扩展方法的实现及其“助手”如下

public class EnumBindingItem<TEnum>
{
    public string Description { get; private set; }
    public TEnum Value { get; set; } // setter needs to be public for the binding to work

    public EnumBindingItem(string description, TEnum value)
    {
        Description = description;
        Value = value;
    }
}

public enum DisplayMode
{
    DescriptionAttribute,
    ValueToString
}

public static class EnumBindingExtension
{
    public static void BindEnum<TEnum>(this ComboBox cbo, DisplayMode mode)
    {
        cbo.DataSource = Enum.GetValues(typeof(TEnum))
                                .Cast<TEnum>()
                                .Select(value => CreateEnumBindingItem(value, mode))
                                .OrderBy(item => item.Value)
                                .ToList();

        cbo.DisplayMember = "Description";
        cbo.ValueMember = "Value";
    }

    private static EnumBindingItem<TEnum> CreateEnumBindingItem<TEnum>(TEnum value, DisplayMode mode)
    {
        string description;

        if (mode == DisplayMode.DescriptionAttribute)
        {
            FieldInfo enumMember = typeof(TEnum).GetField(value.ToString());
            DescriptionAttribute attribute = (DescriptionAttribute)
                Attribute.GetCustomAttribute(enumMember, typeof(DescriptionAttribute));
            description = attribute.Description;
        }
        else
        {
            description = value.ToString();
        }

        return new EnumBindingItem<TEnum>(description, value);
    }
}

ComboBoxSelectedValueChanged 事件处理程序中,您可以轻松地获取所选的 Enum 值,如下所示

private void AnimalComboBoxSelectedValueChanged(object sender, EventArgs e)
{
    AnimalOption selectedAnimal = ((EnumBindingItem<AnimalOption>)AnimalComboBox.SelectedItem).Value;

    AnimalSelectionLabel.Text = selectedAnimal.ToString();
}

private void ShapeComboBoxSelectedValueChanged(object sender, EventArgs e)
{
    ShapeOption selectedShape = ((EnumBindingItem<ShapeOption>)ShapeComboBox.SelectedItem).Value;

    ShapeSelectionLabel.Text = selectedShape.ToString();
}

希望对您有所帮助! 欢迎提出评论!

历史

  • v1.1 - 2015年3月16日
    • 合并了 Klaus Luedenscheidt 的建议和 Sergey Alexandrovich Kryukov 的一个建议。 没有功能性更改。
  • v1.0 - 2015年3月15日
© . All rights reserved.