应用场景:在项目中,我们已习惯将较稳定的分类标准定义为枚举,来保证程序中取值的合法性,也使代码更清晰。某些情况下我们需要在DropDownList等选择控件上绑定某个枚举的所有枚举值,供用户自行选择,这时就需要将枚举值转换为DropDownList等的选项值。
最初遇到这种需求时,我随手写了个简单的方法如下。
- 枚举定义
/// <summary> /// 紧急程度 /// </summary> public enum eOA_EmergencyLevel { /// <summary> /// 平件 /// </summary> 平件 = 1, /// <summary> /// 急件 /// </summary> 急件 = 2 }
- 将枚举转换成ArrayList
/// <summary> /// 将枚举转换成ArrayList /// </summary> /// <returns></returns> public static IList EnumToList(Type enumType) { ArrayList list = new ArrayList(); foreach (int i in Enum.GetValues(enumType)) { ListItem listitem = new ListItem(Enum.GetName(enumType, i), i.ToString()); list.Add(listitem); } return list; }
- 绑定
/// <summary> /// 将枚举转换成下拉框 /// </summary> public static void FillDropDownList(DropDownList ddl, Type enumType) { ddl.Items.Clear(); ddl.DataSource = EnumToList(enumType); ddl.DataValueField = "value"; ddl.DataTextField = "text"; ddl.DataBind(); }
后来,在同事讨论代码时,被大家批评为不该使用这种中文的枚举名称;同时我自己也觉得这种反射方式性能有问题。不过因为影响不大,一直懒得去理它。
最近看到了两篇博文(枚举的显示和绑定和一个利用扩展方法的实例:AttachDataExtensions),是利用C# 3.0的扩展方法实现的,实现得很是优美,可惜我们的项目基于.NET 2.0,用不上。但受此启发,便花了点时间使用Attribute和缓存的技术重构了原来的代码。
- EnumShowNameAttribute
/// <summary> /// 枚举的显示名称 /// </summary> [global::System.AttributeUsage(AttributeTargets.Field, Inherited = false, AllowMultiple = false)] public sealed class EnumShowNameAttribute : Attribute { private string showName; /// <summary> /// 显示名称 /// </summary> public string ShowName { get { return this.showName; } } /// <summary> /// 构造枚举的显示名称 /// </summary> /// <param name="showName">显示名称</param> public EnumShowNameAttribute(string showName) { this.showName = showName; } }
- 枚举定义
/// <summary> /// 紧急程度 /// </summary> public enum eOA_EmergencyLevel { /// <summary> /// 平件 /// </summary> [EnumShowName("平件")] Common = 1, /// <summary> /// 急件 /// </summary> [EnumShowName("急件")] Emergency = 2 }
- 枚举工具类
/// <summary> /// 枚举工具类 /// </summary> public sealed class EnumUtil { private static Dictionary<string, Dictionary<int, string>> _EnumList = new Dictionary<string, Dictionary<int, string>>(); //枚举缓存池 /// <summary> /// 将枚举绑定到ListControl /// </summary> /// <param name="listControl">ListControl</param> /// <param name="enumType">枚举类型</param> public static void FillListControl(ListControl listControl, Type enumType) { listControl.Items.Clear(); listControl.DataSource = EnumToDictionary(enumType); listControl.DataValueField = "key"; listControl.DataTextField = "value"; listControl.DataBind(); } /// <summary> /// 将枚举转换成Dictionary<int, string> /// Dictionary中,key为枚举项对应的int值;value为:若定义了EnumShowName属性,则取它,否则取name /// </summary> /// <param name="enumType">枚举类型</param> /// <returns></returns> public static Dictionary<int, string> EnumToDictionary(Type enumType) { string keyName = enumType.FullName; if (!_EnumList.ContainsKey(keyName)) { Dictionary<int, string> list = new Dictionary<int, string>(); foreach (int i in Enum.GetValues(enumType)) { string name = Enum.GetName(enumType, i); //取显示名称 string showName = string.Empty; object[] atts = enumType.GetField(name).GetCustomAttributes(typeof(EnumShowNameAttribute), false); if (atts.Length > 0) showName = ((EnumShowNameAttribute)atts[0]).ShowName; list.Add(i, string.IsNullOrEmpty(showName) ? name : showName); } object syncObj = new object(); if (!_EnumList.ContainsKey(keyName)) { lock (syncObj) { if (!_EnumList.ContainsKey(keyName)) { _EnumList.Add(keyName, list); } } } } return _EnumList[keyName]; } /// <summary> /// 获取枚举值对应的显示名称 /// </summary> /// <param name="enumType">枚举类型</param> /// <param name="intValue">枚举项对应的int值</param> /// <returns></returns> public static string GetEnumShowName(Type enumType, int intValue) { return EnumToDictionary(enumType)[intValue]; } }
想更偷懒的话,还可以省掉自定义的EnumShowNameAttribute,直接用System.ComponentModel.DescriptionAttribute就行了。
source: http://www.cnblogs.com/wenjian/archive/2009/06/19/1506550.html
枚举的显示和绑定 http://www.cnblogs.com/zhucai/archive/2009/05/27/enum_bind.html