繁体   English   中英

使用带有枚举项的c#winforms数据绑定时,如何在组合框中获得友好的文本描述?

[英]How can I get friendly text descriptions in a combo box when using c# winforms data binding with enum items?

我有几个ComboBox控件,其中DropDownStyle设置为DropDownList。 选择的项目是枚举值,但我希望显示这些值的“友好”描述,即带空格而不是驼峰式大小写。

我希望组合框被“双向”绑定到数据对象:如果数据对象更改其属性,它将更改组合框,反之亦然。

我可以使用字符串轻松地做到这一点,但是问题是我将控件绑定到对象中的枚举属性,因此我希望组合框的Items集合包含实际枚举。 这显然是行不通的。

解决方案1:文字属性

我可以在对象中创建文本属性,然后将其映射到枚举值。 但是,这有点混乱,因为我在业务逻辑层中包含了真正属于UI的内容。 在该业务逻辑层中,它们应该是枚举而不是字符串。

解决方案2:事件处理常式

另一种选择是使用事件处理程序,以便当用户更改选项时,它会获取选定的项目文本并找到适当的枚举值,然后在对象中进行设置。 这只是绑定的一种方式。

尝试解决方案3

public class BusinessObject
{
    private NumberCategory category;

    public NumberCategory Category
    {
        get
        {
            return category;
        }
        set
        {
            category = value;
        }
    }
}

public enum NumberCategory
{
    [Description("Negative Number")]
    NegativeNumber,

    [Description("Zero")]
    Zero,

    [Description("One")]
    One,

    [Description("Prime Number")]
    PrimeNumber,

    [Description("Composite Number")]
    CompositeNumber,
}

public class EnumDescriptionAdapter
{
    private readonly BusinessObject businessObject;

    public EnumDescriptionAdapter(BusinessObject businessObject)
    {
        this.businessObject = businessObject;
    }

    public string CategoryValue
    {
        get
        {
           //get the enum from businessObject and convert to a string
            return EnumUtils.GetDescription(businessObject.Category);
        }

        set
        {
            //get the string, convert to an enum and set it in BusinessObject
            businessObject.Category = EnumUtils.GetValueFromDescription<NumberCategory>(value); 
        }
    }
}

public static class EnumUtils 
{

    public static T GetValueFromDescription<T>(string description)
    {
        var type = typeof(T);
        if (!type.IsEnum) throw new InvalidOperationException();
        foreach (var field in type.GetFields())
        {
            var attribute = Attribute.GetCustomAttribute(field,
                typeof(DescriptionAttribute)) as DescriptionAttribute;
            if (attribute != null)
            {
                if (attribute.Description == description)
                    return (T)field.GetValue(null);
            }
            else
            {
                if (field.Name == description)
                    return (T)field.GetValue(null);
            }
        }
        throw new ArgumentException("Not found.", "description");
        // or return default(T);
    }

    public static string GetDescription(Enum value)
    {
        Type type = value.GetType();
        string name = Enum.GetName(type, value);
        if (name != null)
        {
            FieldInfo field = type.GetField(name);
            if (field != null)
            {
                DescriptionAttribute attr =
                       Attribute.GetCustomAttribute(field,
                         typeof(DescriptionAttribute)) as DescriptionAttribute;
                if (attr != null)
                {
                    return attr.Description;
                }
            }
        }
        return null;
    }
}

public partial class Form1 : Form
{
    public BusinessObject businessObject;

    public Form1()
    {
        InitializeComponent();

        string[] descriptions = Enum.GetValues(typeof(NumberCategory)).Cast<NumberCategory>().Select(e => EnumUtils.GetDescription(e)).ToArray();

        comboBox1.DataSource = descriptions;

        businessObject = new BusinessObject();
        EnumDescriptionAdapter adapter = new EnumDescriptionAdapter(businessObject);

        comboBox1.DataBindings.Add(new Binding("SelectedItem", adapter, "CategoryValue"));
    }

    private void button1_Click(object sender, EventArgs e)
    {
        businessObject.Category = NumberCategory.PrimeNumber;
    }
}

我在表单上放置了一个按钮( button1 )和一个组合框( comboBox1 )。 当我更改组合框选定的项目时,它确实会触发EnumDescriptionAdapter.CategoryValue的setter并更改businessObject 但是,事实并非如此:如果按下按钮,它将更改businessObject但不会更改comboBox1的选定项。

我不知道它是否更优雅,但是您可以创建一个具有2个属性的类,一个用于显示,另一个作为值。 然后,从枚举中以一种或另一种方式填充此类创建的列表。

您会认识到用表示层材料装饰业务层材料被认为不是好习惯,这让您大为赞赏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM