http://www.cnblogs.com/michaellu/articles/1226431.html 原文
摘要:在程序设计过程中经常会遇到一些数据是以枚举值的形式提供给用户进行选择或查看,通常情况下,枚举数据都是已英文的方式或者便于程序中使用的方式来设置的。在显示枚举类型的数据是又通常是使用ToString()的方式将枚举数据显示出来,在通过PropertyGrid显示给用户时感觉不是很友好,很多用户希望能够以中文的方式显示出来。本文就以实例的方式介绍如何在程序中实现PropertyGrid中友好显示的方式,而又不影响Enum类型的数据在其他地方的使用。
一、引文
PropertyGrid 中显示对象属性值的方式的特殊设置是可以通过简单的在属性上添加相应的特性标签,比如EditorAttribute(数据编辑控件)、 TypeConverter(数据输入和显示控制)、Category(属性分类)、DescriptionAttribute(属性描述信息)。为了完成枚举类型的数据显示,这里主要使用的是EditorAttribute和TypeConverter来实现的。首先要创建用于在 PropertyGrid中显示枚举类型数据并允许用户进行选择的控件,然后从UITypeEditor派生一个EnumTypeEditor类,并重写 UITypeEditorEditStyle方法以及EditValue方法用于使得列表中的数据显示为中文,另外还要从TypeConverter派生一个EnumConverter类,并重写CanConvertTo方法、ConvertTo方法用于属性显示为中文。下面将给出具体的实现方法。
二、实现方法及实验
1、新建一个枚举类型,每个类型都给指定一个中文的描述特性标签。如下面代码所示:
public enum MarqueeLightShape
{
[Description("正方形")]
Square,
[Description("圆形")]
Circle,
[Description("三角形")]
Triangle,
[Description("测试")]
Test
}
2、新建一用于显示枚举类型所有数据的列表控件。新建一个用户控件,在其中添加一个ListBox,设置其数据源以及显示成员和值成员。
public partial class UserCombox : UserControl
{
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;//根据当前对象的枚举值设置列表中应该选中的项
this.Height = listBox1.ItemHeight*listBox1.Items.Count+5;//设置列表控件的高度为列表项能够全部显示出来并且再多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();
}
}
3、从UITypeEditor派生一个EnumTypeEditor类,并重写UITypeEditorEditStyle方法以及EditValue方法用于使得列表中的数据显示为中文。
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 = mComBox.MyValue;//将列表控件中用于选定的值赋值给需要返回的Value
}
return value;
}
}
4、从TypeConverter派生一个EnumConverter类,并重写CanConvertTo方法、ConvertTo方法用于属性显示为中文
internal class EnumConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return true;
}
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!";
}
}
5、给需要显示中文描述的对象属性添加特性标签。
private MarqueeLightShape mTestEnum ;
[DescriptionAttribute("Test 枚举值."),
EditorAttribute(typeof(EnumTypeEditor), typeof(System.Drawing.Design.UITypeEditor)),
]
[TypeConverter(typeof(EnumConverter))]
public MarqueeLightShape TestEnum
{
get { return mTestEnum; }
set { mTestEnum = value; }
}
6、显示效果图