属性的编辑器需要通过给属性加入[EditorAttribute(typeof(MyEditor), typeof(System.Drawing.Design.UITypeEditor)) ]属性,将属性与自定义编辑器绑定。编辑器的好处是可以提供UI来支持用户定义的特殊结构属性。通过编辑器和自定义UI可以实现诸如本地化enum值 等特殊要求。且代码容易理解。自定义UI可以通过图形化设计窗口轻松实现。
其代码如下:
public enum Test//测试用枚举结构
{
[LocalizeDescription("ENUM_A")]
aaaa = 0,
[LocalizeDescription("ENUM_B")]
bbbb,
[LocalizeDescription("ENUM_C")]
cccc
}
class ...
{
...
[EditorAttribute(typeof(EnumTypeEditor), typeof(System.Drawing.Design.UITypeEditor))] //将编辑器绑``````````//定到TTest属性
[TypeConverter(typeof(EnumConverter))]
public Test TTest
{
get { return test; }
set { test = value; }
}
...
}
public class EnumTypeEditor : UITypeEditor {
public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
//下拉列表方式,即当在PropertyGrid中选中对象的属性后会显示一个下拉列表按钮
}
//控制编辑时数据的显示方式,并返回该一个值作为属性的值。
public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
{
IWindowsFormsEditorService editorService = null;
if (provider != null)
{
editorService =provider.GetService( typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
}
if (editorService != null)
{
//创建显示枚举类型数据的中文描述的控件
UserCombox mComBox = new UserCombox((Enum)value,editorService);
//展开下拉列表在下拉区域显示传入的控件
editorService.DropDownControl(mComBox);
//将列表控件中用于选定的值赋值给需要返回的Value
value = mComBox.MyValue;
}
return value;
}
}
class EnumConverter : TypeConverter
{
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
List<KeyValuePair<Enum, string>> mList = UserCombox.ToListForBind(value.GetType());
foreach (KeyValuePair<Enum, string> mItem in mList)
{
if (mItem.Key.Equals(value))
{
return mItem.Value;
}
}
return "Error!";
}
}
public partial class UserCombox : UserControl//自定义UI
{
private IWindowsFormsEditorService mEditorService = null;
private Enum curValue;
//传入枚举值,以及windowsFormsEditorService控件
public UserCombox(Enum mValue, IWindowsFormsEditorService editorService)
{
InitializeComponent();
mEditorService = editorService;
curValue = mValue;
if (mValue != null)
{
mCurEnumType = mValue.GetType();
if (mCurEnumType != null)
{
if (mCurEnumType.IsEnum)
{
listBox1.DataSource = ToListForBind(mCurEnumType);
listBox1.ValueMember = "Key"; listBox1.DisplayMember = "Value";
//根据当前对象的枚举值设置列表中应该选中的项
listBox1.SelectedValue = curValue;
//设置列表控件的高度为列表项能够全部显示出来并且再多5个像素
this.Height = listBox1.ItemHeight * listBox1.Items.Count + 5;
}
}
}
}
private Type mCurEnumType;
private Enum mValue;
public Enum MyValue
{
get { mValue = this.listBox1.SelectedValue as Enum; return mValue; }
}
//读取枚举类型的描述信息生成显示数据用的列表数据。
public static List<KeyValuePair<Enum, string>> ToListForBind(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
if (!type.IsEnum)
{
throw new ArgumentException("类型必须是枚举型的!", "type");
}
List<KeyValuePair<Enum, string>> list = new List<KeyValuePair<Enum, string>>();
list.Clear();
Array enumValues = Enum.GetValues(type);
foreach (Enum value in enumValues)
{
list.Add(new KeyValuePair<Enum, string>(value, GetDescription(value)));
}
return list;
}
#region GetDescription
/// <summary>
/// 获取枚举类型值的描述信息.
/// </summary>
/// <param name="value">枚举类型<see cref="Enum"/>值</param>
/// <returns>A string containing the text of the <see cref="DescriptionAttribute"/>.</returns>
public static string GetDescription(Enum value)
{
if (value == null)
{
throw new ArgumentNullException("value");
}
string description = value.ToString();
FieldInfo fieldInfo = value.GetType().GetField(description);
//EnumDescriptionAttribute[] attributes = (EnumDescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(EnumDescriptionAttribute), false);
DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes != null && attributes.Length > 0)
{
description = attributes[0].Description;
}
else
{
description = value.ToString();
}
return description;
}
#endregion
//用户选择一项后就收起列表控件
void ListBox1SelectedIndexChanged(object sender, EventArgs e)
{
mEditorService.CloseDropDown();
}
}
PS:部分代码来源于网络,感谢前人。