[英]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.