Hiding properties from the Property Grid
Taking a break from the main components, I decided to get around to writing a small configuration editor using .NET 2.0's lovely ability to edit .config files from code.
I have a custom Section Handler defined for my data, and decided the simplest thing to do would be to stick my custom ConfigurationElement objects onto a PropertyGrid and let the user edit the values directly.
The problem with that is that ConfigurationElement has several public properties that I inherit, and they show up in the grid:
My first instinct to hide them was to implement ICustomTypeDescriptor on my ConfigurationElement and implement GetProperties() so it only returns the properties I want. This turned out to be a ridiculously complicated endeavor, requiring me to implement many methods I don't care about just so I could get to GetProperties, which in turn required me to subclass the PropertyDescriptor class and override lots of properties that I didn't care about either. This whole design-time framework really needs an overhaul - it's way too complicated and the documentation is vague at best.
So I abandoned that approach and immediately set off on achieving my goal in the ugliest, hackiest way I could find. The easiest way to hide a property from the propertygrid is using the [Browsable(false)] attribute. Since the properties are unfortunately non-virtual, I had to hide them in order to override their attributes:
#region
Shadow unneeded properties.[
Browsable(false)]public new bool LockItem { get { return base.LockItem; } set { base.LockItem = value; } }
[
Browsable(false)]public new ElementInformation ElementInformation { get { return base.ElementInformation; } }
[
Browsable(false)]public new ConfigurationLockCollection LockAllAttributesExcept { get { return base.LockAllAttributesExcept; } }
[
Browsable(false)]public new ConfigurationLockCollection LockAllElementsExcept { get { return base.LockAllElementsExcept; } }
[
Browsable(false)]public new ConfigurationLockCollection LockAttributes { get { return base.LockAttributes; } }
[
Browsable(false)]public new ConfigurationLockCollection LockElements { get { return base.LockElements; } } #endregion
I simply hide them behind my new properties, and have those call the base's implementation in case they're actually used for anything.
Result? Works perfectly. Hardly clean, but it works:
11 Comments
Comments have been disabled for this content.
Seth said
Ugly approach, excellent results. Thanks for saving me a week of looking around!
tp said
if i want to conditional hide a property, say LockItem, how do I do that? since using the Browsable(false) attribute will ALWAYS hide LockItem, but what if in some case I want to hide but other case I don't? I can programatically hide it on run-time?
AvnerK said
tp: As I said, this is the quick'n'dirty approach to hiding properties. The more detailed way is to implement ICustomTypeDescriptor and override the GetProperties() method, and then you can choose, at runtime, what properties are exposed. You even have more control, since you can choose to rename the properties shown or do any number of other things. The downside, of course, is that it's more complicated and requires writing a lot of useless code - implementing a method only to add a NotImplementedException and so forth. So far I've managed to avoid doing that, but I know there are solutions on CodeProject that team-members of mine used as reference.
Husko said
Many properties can't be overridden on my custom control. Is there a way around this?
Haukur H. Thorsson said
Hi, Just stumbled upon this article of yours, sounds exactly like what I need to do. Ugly? true, a hack? yes, but it does the trick.
Someone From The South said
How is this a dirty approach? It's what the Browsable property is designed to do.
Nathan said
Mistrzostwo w swojej prostocie!!!
Question said
Hello, This is a very good approach, but this code is a CSharp code. My own code is written in C++.Net code, so how can i do the same for this issue. Your fast reply is highly recommended. Thanks, best regards
Matt said
Thanks, I don't think this is really hacky at all. Very successful way to hide them.
Trevor said
Thanks save me a whole host of messing.
C said
Its only hackish because the new keyword had to be used. If they were virtual properties and an override could be used this would be a perfect fix. Still good though and works well.