Home > Enterprise >  Changing the browsability of a property at runtime
Changing the browsability of a property at runtime

Time:10-25

I have a PropertyGrid in my winforms application that displays the some of the selected object's properties. I want that a certain property will be sometimes displayed and somtimes won't, by my choice, (lets assume the the browsability changes every time a specific button is pressed at runtime). Setting-up the browsability before runtime is pretty easy, using the BrowsableAttribute, from what I understand that attributes are set at design time hence I need another solution. In many places I found this piece of code:

public static void ChangeBrowsability(SomeObject obj, string propertyName, bool isBrowsable)
{//usage: supposed to change browsability at runtime
        PropertyDescriptor descriptor = TypeDescriptor.GetProperties(obj)[propertyName];
        BrowsableAttribute attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
        FieldInfo browsableField = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
        browsableField.SetValue(attrib, isBrowsable);
}

The first problem is the browsableField is always null for some reason, and I would like to know why. Also an alternative solution to this code may be welcomed.

CodePudding user response:

You can't change the reality of how attributes are defined - they are baked into the IL; however, you can lie and cheat. The winforms PropertyGrid doesn't go directly to reflection - it uses an indirect route via TypeDescriptor, and TypeDescriptor defaults to using reflection. However, you can implement your own descriptor implementations that change everything, in particular (for this case): PropertyDescriptor.IsBrowsable. That's the good news.

The bad news that this is hard. Like; really hard; you'd have to really, really care about this feature to use it. It involves:

  • capturing the outgoing reflection-based ICustomTypeDescriptor, so you can use it as a foundation
  • implementing your own ICustomTypeDescriptor that exposes the properties as a "decorator"
  • registering a TypeDescriptionProvider that exposes your own type descriptor
  • capturing the outgoing reflection-based PropertyDescriptorCollection so you can use them as a foundation
  • implementing your own decorators of the PropertyDescriptors, forwarding most of the APIs, except for IsBrowsable where you would add your own logic

Doable, but: very complex and convoluted, and honestly: using APIs that are largely out of fashion and which haven't seen love in a decade. A worked example could easily run into the hundreds of lines of C#, so is beyond what I can reasonably supply here.

  • Related