7

I am doing a project that allows user to customized the properties of a Control. I have a form that has a control like Label, TextBox, Button and PropertyGrid control. When the user clicks on the Label i am showing the properties of the Label in the ProeprtyGrid which is all working fine using below code:

propertyGrid1.SelectedObject = SelectedControl;

But I just want to show some properties like BackColor, Font, ForeColor, Text. Is it possible to hide the properties since I don't want user to change it or show to them? If yes, how?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Zhyke
  • 427
  • 7
  • 22

2 Answers2

8

I believe you are looking for custom type descriptors.

While the other answer is sharing correct information about Browsable attribute and BrowsableAttributes of PropertyGrid, but I'd say it's not a proper practical solution for the problem.

It's not practical to set Browsable attribute, or any other custom attributes for existing control classes like Label, Button, and so on. Because in this way, the op needs to override all properties of those classes and decorate them with suitable attribute. And even worst, not all propertied are overridable.

What's the practical solution?

As I mentioned earlier, I believe you are looking for custom type descriptors. You can provide metadata about an object assigning a new TypeDescriptor or implementing ICustomTypeDescriptor or deriving from CustomTypeDescriptor.

Example

Here for example, I create a CustomObjectWrapper class deriving from CustomTypeDescriptor which accepts an object in constructor. This way I can simply filter the properties of the wrapped object by overriding GetProperties.

Then instead of assigning button1 to PropertyGrid, I wrap it in CustomObjectWrapper and assing the CustomObjectWrapper to property grid. This way it just shows the filtered properties and the properties are actually come from button1.

Here is the implantation:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public class CustomObjectWrapper : CustomTypeDescriptor
{
    public object WrappedObject { get; private set; }
    public List<string> BrowsableProperties { get; private set; }
    public CustomObjectWrapper(object o)
        :base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
    {
        WrappedObject = o;
        BrowsableProperties = new List<string>() { "Text", "BackColor" };
    }
    public override PropertyDescriptorCollection GetProperties()
    {
        return this.GetProperties(new Attribute[] { });
    }
    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
                             .Where(p=>BrowsableProperties.Contains(p.Name))
                             .Select(p => TypeDescriptor.CreateProperty(
                                 WrappedObject.GetType(),
                                 p,
                                 p.Attributes.Cast<Attribute>().ToArray()))
                             .ToArray();
        return new PropertyDescriptorCollection(properties);
    }
}

And as usage:

propertyGrid1.SelectedObject = new CustomObjectWrapper(button1);

You can simply add new property names to BrowsableProperties of the CustomObjectWrapper. It's a public property.

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    What do you think about having a Designer class that inherits [ControlDesigner](https://msdn.microsoft.com/en-us/library/system.windows.forms.design.controldesigner%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396) and overrides its [PreFilterProperties](https://msdn.microsoft.com/en-us/library/system.componentmodel.design.componentdesigner.prefilterproperties(v=vs.110).aspx)? The `properties` parameter is a `IDictionary`. Properties could then be removed using `properties.Remove("[PropertyName]")`. – Jimi Jul 31 '18 at 21:57
  • I tried this one and it's works great. Thank you so much. – Zhyke Aug 01 '18 at 02:11
  • @Jimi Thanks for the feedback. If the requirement was for design-time, I'd used `ControlDesigner`, like [this post](https://stackoverflow.com/a/38771092/3110834) or [this one](https://stackoverflow.com/a/50772584/3110834). But here the OP is asking it for run-time, by setting `propertyGrid1.SelectedObject`. That's why I used `TypeDescriptor`. – Reza Aghaei Aug 01 '18 at 03:05
  • Yes, of course. I was more interested in your opinion on the matter (eventual problem, drawbacks...). Btw, those answers didn't come up on a search. That's a bummer. – Jimi Aug 01 '18 at 09:30
5

UPDATE

Please note this is only useful for Hiding properties (when you can). Reza Aghaei answer is actually the correct answer.

I'll leave this here as it's suitable for the other case when you just simply want to hide a property when you have access to it.

Original

Easiest way is probably to use

[Browsable(false)]

BrowsableAttribute Class

Specifies whether a property or event should be displayed in a Properties window.

[Browsable(false)]
public int SecretSquirrels
{
  get; set;
}

Also as pointed out by Marc Gravell, there is also

PropertyGrid.BrowsableAttributes Property

Gets or sets the browsable attributes associated with the object that the property grid is attached to.

halfer
  • 19,824
  • 17
  • 99
  • 186
TheGeneral
  • 79,002
  • 9
  • 103
  • 141
  • 1
    generalizing that a bit, there is a [`BrowsableAttributes`](https://msdn.microsoft.com/en-us/library/system.windows.forms.propertygrid.browsableattributes(v=vs.110).aspx) property that you can use to provide custom filters (or : different views on the same object), but: it is *quite likely* that `[Browsable(false)]` does everything OP needs – Marc Gravell Jul 31 '18 at 11:07
  • Thanks. Do I need to create a Custom `PropertyGrid`? Say I want to show this list `string[] ShowThisPropertyList = new string[] { "Text", "BackColor", "ForeColor" };` – Zhyke Jul 31 '18 at 12:45
  • @Zhyke You are probably doing to have to create a new object that reference the properties in the label you want, and thats the one you put in the propertyGrid – TheGeneral Jul 31 '18 at 12:48
  • While this answer is sharing correct information about `Browsable` attribute and `BrowsableAttributes` of `PropertyGrid`, but I'd say it's not a proper practical solution for the problem. It's not practical to set `Browsable` attribute, or any other custom attributes for existing control classes like `Label`, `Button`, and so on. Because in this way, the op needs to override all properties of those classes and decorate them with suitable attribute. And even worst, not all propertied are overridable. – Reza Aghaei Jul 31 '18 at 17:19