0

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.

Mayerstro
  • 23
  • 4
  • Attribute information is stored in metadata and is compiles into the assembly at compile time – Flydog57 Oct 18 '21 at 15:05
  • Duplicates: [one](https://stackoverflow.com/questions/31321637/changing-browsable-attribute-at-runtime-c), [two](https://stackoverflow.com/questions/13673101/how-do-you-control-what-is-visible-in-a-property-grid-at-runtime), [three](https://stackoverflow.com/questions/4690481/conditional-browsable-attribute), etc... – Hans Passant Oct 18 '21 at 16:38
  • You can implement a TypeConverter for your class and return whatever properties you want by overriding the GetProperties method. You don't have to use the BrowsableAttribute. You can get some hints [here](https://stackoverflow.com/a/68941835/10318835). – Steeeve Oct 18 '21 at 18:27

1 Answers1

0

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.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Thank you, so what is the alternaive? – Mayerstro Oct 20 '21 at 08:53
  • @Mayerstro alternative: https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.propertygrid.browsableattributes?view=windowsdesktop-5.0 - play with that, and specify *alternative* attributes that indicate browsability in different scenarios, and annotate your types accordingly – Marc Gravell Oct 20 '21 at 08:56
  • @Mayerstro I don't understand the question; can you clarify? – Marc Gravell Oct 20 '21 at 08:57