主要原理是在枚举上添加DescriptionAttribute属性,然后通过反射将其显示出来
方法1:继承StringConverter类
public class EnumConvertor : StringConverter
{public override bool GetStandardValuesSupported(ITypeDescriptorContext context){return true;}public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value){if (!(value is string)) return base.ConvertFrom(context, culture, value);var type = context.GetValue<Type>("PropertyType");var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(f =>{if (!(f.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)) return false;return description.Description.Equals(value.ToString());});if (type != null && field != null)return Enum.Parse(type, field.Name);return base.ConvertFrom(context, culture, value);}public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType){// 将Enum类型转换成string进行显示if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType);var type = context.GetValue<Type>("PropertyType");var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(f => f.Name.Equals(value.ToString()));if (field != null && field.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)return description.Description;return base.ConvertTo(context, culture, value, destinationType);}public override StandardValuesCollectionGetStandardValues(ITypeDescriptorContext context){List<string> list = new List<string>();var type = context.GetValue<Type>("PropertyType");foreach (var info in type.GetFields(BindingFlags.Public | BindingFlags.Static)){if (!(info.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description))continue;list.Add(description.Description);}return new StandardValuesCollection(list);}
}
方法2:自定义界面显示
public class EnumEditor : UITypeEditor
{private class EnumItem{public object Value { get; set; }public string Name { get; set; }}public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context){return UITypeEditorEditStyle.DropDown;}public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value){bool cancel;if (provider == null) return value;if (!(provider.GetService(typeof(IWindowsFormsEditorService)) is IWindowsFormsEditorService editorService))return value;ListBox listBox = new ListBox{DisplayMember = "Name",// 这里需要将DrawMode设置成OwnerDrawVariable才可以设置ItemHeightDrawMode = DrawMode.OwnerDrawVariable,//IntegralHeight = true,Font = provider.GetValue<PropertyGrid>("OwnerGrid").Font,SelectionMode = SelectionMode.One};listBox.DrawItem += (sender, args) =>{args.DrawBackground();args.DrawFocusRectangle();StringFormat strFmt = new StringFormat();// 文本水平居中// strFmt.Alignment = StringAlignment.Center;// 文本垂直居中(根据需求进行设置)strFmt.LineAlignment = StringAlignment.Center; args.Graphics.DrawString((listBox.Items[args.Index] as EnumItem)?.Name, args.Font,new SolidBrush(args.ForeColor), args.Bounds, strFmt);};listBox.MouseClick += (sender, args) =>{int index = ((ListBox)sender).IndexFromPoint(args.Location);if (index < 0) return;editorService.CloseDropDown();};listBox.KeyDown += (sender, args) =>{if (args.KeyCode != Keys.Enter) return;editorService.CloseDropDown();};listBox.PreviewKeyDown += (sender, args) =>{if (args.KeyCode != Keys.Escape) return;cancel = true;editorService.CloseDropDown();};if (value != null){Type enumType = value.GetType();if (!enumType.IsEnum) throw new InvalidOperationException();foreach (FieldInfo fi in enumType.GetFields(BindingFlags.Public | BindingFlags.Static)){EnumItem item = new EnumItem{Value = fi.GetValue(null)};object[] attributes = fi.GetCustomAttributes(typeof(DescriptionAttribute), true);item.Name = attributes.Length > 0? (attributes[0] as DescriptionAttribute)?.Description: fi.Name;int index = listBox.Items.Add(item);if (fi.Name == value.ToString())listBox.SetSelected(index, true);}}listBox.ItemHeight += 6;// 设置列表显示的高度listBox.Height = listBox.ItemHeight * listBox.Items.Count + 3;cancel = false;editorService.DropDownControl(listBox);return cancel || listBox.SelectedIndices.Count == 0 ? value : (listBox.SelectedItem as EnumItem)?.Value;}
}public class EnumConverter : TypeConverter
{public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType){return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);}public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value){if (!(value is string)) return base.ConvertFrom(context, culture, value);var type = context.GetValue<Type>("PropertyType");var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(f =>{if (!(f.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)) return false;return description.Description.Equals(value.ToString());});if (type != null && field != null)return Enum.Parse(type, field.Name);return base.ConvertFrom(context, culture, value);}public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType){return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);}public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,Type destinationType){// 将Enum类型转换成string进行显示if (destinationType != typeof(string)) return base.ConvertTo(context, culture, value, destinationType);var type = context.GetValue<Type>("PropertyType");var field = type?.GetFields(BindingFlags.Public | BindingFlags.Static).FirstOrDefault(f => f.Name.Equals(value.ToString()));if (field != null && field.GetCustomAttribute(typeof(DescriptionAttribute)) is DescriptionAttribute description)return description.Description;return base.ConvertTo(context, culture, value, destinationType);}
}
使用
[Editor(typeof(EnumEditor), typeof(UITypeEditor)),TypeConverter(typeof(Forms.Utility.EnumConverter))]
public enum Alignment
{[Description("无")]None,[Description("居左")]Left,[Description("居中")]Center,[Description("居右")]Right
}