寻找在调用属性的get时触发的事件

时间:2012-04-29 13:00:57

标签: c# winforms propertygrid

我在我的应用程序中使用PropertyGrid。我需要在运行时更改自定义数据条件的某些属性的可见性和只读。

虽然我没有找到容易的东西。准备好了,我通过在运行时更改ReadOnlyAttributeBrowsableAttribute属性找到了一种解决方法,如下所示:

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调用这些方法的任何事件吗?也许通过实现一个接口。

1 个答案:

答案 0 :(得分:1)

调用property-get时,没有内置事件触发,除非你写一个。

当然,如果你编写一个自定义描述符(PropertyDescriptor,通常链接到反射描述符作为装饰器),你可以通过描述符拦截访问 (数据绑定等),并做任何事情你想要 - 但对于任意类型(包括你没有写的那些)。

在运行时通过反射设置属性值...不太好。这很大程度上是由于TypeDescriptor缓存的意外。如果要这样做,最好使用TypeDescriptor.AddAttributes(或类似)。但是,通过实现自定义模型,您正在尝试做的更为合适。根据您显示此处的位置,可以通过一个或:

完成
  • 添加自定义TypeConverter,覆盖GetProperties,并根据数据在运行时提供自定义描述符 - 主要用于PropertyGrid
  • 在对象中实现ICustomTypeDescriptor,实现GetProperties,并根据数据在运行时提供自定义描述符 - 适用于大多数控件
  • 添加自定义TypeDescriptionProvider并与类型(TypeDescriptor.AddProvider)关联,提供行为类似于上面的ICustomTypeDescriptor;这将对象与描述符voodoo
  • 分开

这些都很棘手!最简单的是TypeConverter选项,因为你提到了PropertGrid,它运行良好。继承自ExpandableObjectConverter,并根据需要覆盖GetProperties,过滤,并根据需要为只读属性提供自定义描述符。然后将TypeConverterAttribute附加到您的类型,指定您的自定义转换器类型。

重点:.NET的这个分支相当复杂,模糊不清,并且使用量逐渐减少。但它确实有效。