话说 PropertyDescriptor 的许多属性都是只读的。包括 DisplayName 属性,最初的时候,用Reflector 反编译然后查看里面的私有字段和属性,然后用反射机制强行设置,虽然 PropertyDescriptor 的 DisplayName 属性已经显示正确了,但 Html.LabelFor 生成的 HTML 代码还是不显示 DisplayName 的内容。。
利用 Reflector 继续搜索各个类之间的关系,发现PropertyDescriptor 的父类 MemberDescriptor 的 AttributeArray 属性中包含有全部属性的原始实例。后来将其 反射出来,再设置回去,果然成功。Html.LabelFor 中显示的内容也正确了。
1、
// 摘要:
// 表示一个类成员,例如某个属性或事件。这是一个抽象基类。
[ComVisible(true)]
public abstract class MemberDescriptor
{
// 摘要:
// 用指定的成员名称和特性数组初始化 System.ComponentModel.MemberDescriptor 类的新实例。
//
// 参数:
// name:
// 成员名。
//
// attributes:
// 包含成员特性的类型 System.Attribute 的数组。
//
// 异常:
// System.ArgumentException:
// 该名称为空字符串 ("") 或 null。
protected MemberDescriptor(string name, Attribute[] attributes); //初始化
// 摘要:
// 获取或设置特性数组。
//
// 返回结果:
// 包含成员特性的类型 System.Attribute 的数组。
protected virtual Attribute[] AttributeArray { get; set; } //可写,重写Attribute使DisplayName 属性值可写
//
// 摘要:
// 获取可以显示在窗口(如“属性”窗口)中的名称。
//
// 返回结果:
// 为该成员显示的名称。
public virtual string DisplayName { get; } //只读
//
// 摘要:
// 获取成员的说明,如 System.ComponentModel.DescriptionAttribute 中所指定的。
//
// 返回结果:
// 成员的说明。如果没有 System.ComponentModel.DescriptionAttribute,属性值被设置为默认值,它是一个空字符串
// ("")。
public virtual string Description { get; }
}
2、
子类中覆盖一下属性DisplayName:
public class PropertyStub : PropertyDescriptor
{
PropertyInfo info;
public PropertyStub(PropertyInfo propertyInfo, Attribute[] attrs)
: base(propertyInfo.Name, attrs)
{
this.info = propertyInfo;
}
//通过重写DisplayName,可以将属性在PropertyGrid中的显示设置成中文
public override string DisplayName
{
get
{
if (info != null)
{
MyControlAttibute uicontrolattibute = (MyControlAttibute)Attribute.GetCustomAttribute(info, typeof(MyControlAttibute));
if (uicontrolattibute != null)
return uicontrolattibute.PropertyName;
else
{
return info.Name;
}
}
else
return "";
}
}
}
3、
//重写Attribute的属性
public class MyControlAttibute : Attribute
{
private string _PropertyName;
private string _PropertyDescription;
private object _DefaultValue;
public MyControlAttibute(string Name, string Description, object DefalutValue)
{
this._PropertyName = Name;
this._PropertyDescription = Description;
this._DefaultValue = DefalutValue;
}
public MyControlAttibute(string Name, string Description)
{
this._PropertyName = Name;
this._PropertyDescription = Description;
this._DefaultValue = "";
}
public MyControlAttibute(string Name)
{
this._PropertyName = Name;
this._PropertyDescription = "";
this._DefaultValue = "";
}
public string PropertyName
{
get { return this._PropertyName; }
}
public string PropertyDescription
{
get { return this._PropertyDescription; }
}
public object DefaultValue
{
get { return this._DefaultValue; }
}
}