在开发过程中,经常需要将枚举类型与用户界面中的ComboBox控件绑定,以便用户可以从下拉列表中选择一个枚举值。然而,手动将枚举值映射到ComboBox的条目,然后根据用户的选择将其转换回相应的枚举值,这样的代码往往既丑陋又难以维护。幸运的是,C#3.0引入的扩展方法为提供了一个简单而优雅的解决方案。
扩展方法允许为现有类型添加新的方法,而不需要修改其源代码。通过添加对包含扩展方法的类的引用,并在代码中添加相应的命名空间,就可以轻松地将这些方法集成到目标类型中。
为了实现所需的功能,定义了三个方法:
这个方法使用反射来枚举给定枚举类型的所有字段。对于每个字段,它检索Description属性,以便在ComboBox条目中提供更友好的文本。然后,该方法将Description文本及其关联的枚举值添加到ComboBox条目列表中。
以下是BindWithEnum方法的实现:
public static void BindWithEnum<T>(this ComboBox comboBox, T selectedValue)
{
Type enumType = typeof(T);
if (!enumType.IsEnum)
throw new Exception("Only Enum types are allowed.");
List<KeyValuePair<string, T>> comboBoxItems = new List<KeyValuePair<string, T>>();
KeyValuePair<string, T>? selectedItem = null;
foreach (T enumValue in Enum.GetValues(enumType))
{
string name = Enum.GetName(enumType, enumValue);
FieldInfo fi = enumType.GetField(name);
string descriptiveName = fi.GetDescriptionAttributeOrName();
KeyValuePair<string, T> item = new KeyValuePair<string, T>(descriptiveName, enumValue);
comboBoxItems.Add(item);
if (enumValue.Equals(selectedValue))
selectedItem = item;
}
comboBox.DisplayMember = "Key";
comboBox.ValueMember = "Value";
comboBox.DataSource = comboBoxItems;
if (selectedItem != null)
comboBox.SelectedItem = selectedItem.Value;
}
这个方法首先检查传入的类型是否为枚举类型。如果不是,抛出异常。然后,它创建一个列表来存储ComboBox条目,并遍历枚举值以构建ComboBox条目列表。对于每个枚举值,它检索其描述性名称,并将其添加到列表中。最后,它将列表设置为ComboBox的数据源,并根据需要设置初始选择。
这个方法用于检索当前选定的ComboBox条目对应的枚举值。
public static T GetSelectedValue<T>(this ComboBox comboBox)
{
KeyValuePair<string, T> selectedItem = (KeyValuePair<string, T>)comboBox.SelectedItem;
return (T)Convert.ChangeType(selectedItem.Value, typeof(T));
}
这个方法首先获取当前选定的ComboBox条目,然后将其转换为相应的枚举值并返回。
public static void SetSelectedValue<T>(this ComboBox comboBox, T selectedValue)
{
string name = Enum.GetName(typeof(T), selectedValue);
FieldInfo fi = typeof(T).GetField(name);
string descriptiveName = fi.GetDescriptionAttributeOrName();
KeyValuePair<string, T> selectedItem = new KeyValuePair<string, T>(descriptiveName, selectedValue);
comboBox.SelectedItem = selectedItem;
}
这个方法首先获取枚举值的描述性名称,然后创建一个新的ComboBox条目,并将其设置为ComboBox的选定条目。
使用这些扩展方法非常简单。只需在项目中添加对ComboBoxExtensions.dll的引用,并在代码中添加相应的using指令:
using Proxoft.WinForms;
然后,就可以使用这些扩展方法了。以下是一个示例,展示了如何将枚举与ComboBox绑定,并设置和检索当前选择:
[DefaultValue(OptionsToSelectFrom.opt3)]
public enum OptionsToSelectFrom
{
[Description("选项一")]
opt1,
[Description("选项二")]
opt2,
[Description("选项三")]
opt3,
[Description("选项四")]
opt4
}
comboBox1.BindWithEnum<OptionsToSelectFrom>(OptionsToSelectFrom.opt3);
comboBox1.SetSelectedValue<OptionsToSelectFrom>(OptionsToSelectFrom.opt2);
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label1.Text = comboBox1.GetSelectedValue<OptionsToSelectFrom>().ToString();
}