我在我的应用程序中使用PropertyGrid。我需要在运行时更改自定义数据条件的某些属性的可见性和只读。
虽然我没有找到容易的东西。准备好了,我通过在运行时更改ReadOnlyAttribute
和BrowsableAttribute
属性找到了一种解决方法,如下所示:
protected void SetBrowsable(string propertyName, bool value)
{
PropertyDescriptor property = TypeDescriptor.GetProperties(GetType())[propertyName];
BrowsableAttribute att = (BrowsableAttribute)property.Attributes[typeof(BrowsableAttribute)];
FieldInfo cat = att.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
if (property.Attributes.Cast<Attribute>().Any(p => p.GetType() == typeof(BrowsableAttribute)))
cat.SetValue(att, value);
}
protected void SetReadOnly(string propertyName, bool value)
{
PropertyDescriptor property = TypeDescriptor.GetProperties(GetType())[propertyName];
ReadOnlyAttribute att = (ReadOnlyAttribute)property.Attributes[typeof(ReadOnlyAttribute)];
FieldInfo cat = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
if (property.Attributes.Cast<Attribute>().Any(p => p.GetType() == typeof(ReadOnlyAttribute)))
cat.SetValue(att, value);
}
现在,我的问题是我应该在哪里调用这些方法?我可以处理object
调用这些方法的任何事件吗?也许通过实现一个接口。
答案 0 :(得分:1)
调用property-get时,没有内置事件触发,除非你写一个。
当然,如果你编写一个自定义描述符(PropertyDescriptor,通常链接到反射描述符作为装饰器),你可以通过描述符拦截访问 (数据绑定等),并做任何事情你想要 - 但对于任意类型(包括你没有写的那些)。
在运行时通过反射设置属性值...不太好。这很大程度上是由于TypeDescriptor缓存的意外。如果要这样做,最好使用TypeDescriptor.AddAttributes(或类似)。但是,通过实现自定义模型,您正在尝试做的更为合适。根据您显示此处的位置,可以通过一个或:
完成这些都很棘手!最简单的是TypeConverter选项,因为你提到了PropertGrid,它运行良好。继承自ExpandableObjectConverter,并根据需要覆盖GetProperties,过滤,并根据需要为只读属性提供自定义描述符。然后将TypeConverterAttribute附加到您的类型,指定您的自定义转换器类型。
重点:.NET的这个分支相当复杂,模糊不清,并且使用量逐渐减少。但它确实有效。