Tuguldur
Tuguldur

Reputation: 31

How to add custom Visible property that doesn't hide the control to PropertyGrid?

I'm writing a program that user can edit the control properties in the Form. To change control(textbox, label etc.) properties I am using PropertyGrid. And I want to add custom Visible property that doesn't hide the control when it becomes False on runtime. To change the visibility only when save the changes.

I am using Hide some properties in PropertyGrid at run-time 's solution to show specific properties of the control like {Text, BackColor, ForeColor, Font, Size, Location, Visible} etc.

private void CreateUIEditor(Control c)
{
    if (c is Label)
    {
        propertyGrid.SelectedObject = new CustomObjectWrapper(c, new List<string>() 
        { "Text", "BackColor", "ForeColor", "Font", "Visible"});
    }
    //...
}
public class CustomObjectWrapper : CustomTypeDescriptor
{
    public object WrappedObject { get; private set; }
    public List<string> BrowsableProperties { get; private set; }
    public CustomObjectWrapper(object o, List<string> pList)
        : base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
    {
        WrappedObject = o;
        BrowsableProperties = pList;
    }
    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);
    }
}

Upvotes: 1

Views: 855

Answers (1)

Reza Aghaei
Reza Aghaei

Reputation: 125197

The basic idea here is to have a shadow property which doesn't belong to the original object, but is showing in the PropertyGrid. Such a property can belong to the proxy class itself.

The following proxy class will hide the original Visible property, however it shows a Visible property which you can change but will not change the visibility of the original object:

enter image description here

Here's the code:

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, List<string> pList)
        : base(TypeDescriptor.GetProvider(o).GetTypeDescriptor(o))
    {
        WrappedObject = o;
        BrowsableProperties = pList;
    }
    public override PropertyDescriptorCollection GetProperties()
    {
        return this.GetProperties(new Attribute[] { });
    }
    public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
    {
        var properties = base.GetProperties(attributes).Cast<PropertyDescriptor>()
             .Where(p => p.Name != "Visible")
             .Where(p => BrowsableProperties.Contains(p.Name))
             .Select(p => TypeDescriptor.CreateProperty(
                 WrappedObject.GetType(),
                 p,
                 p.Attributes.Cast<Attribute>().ToArray()))
             .ToList();
        if (BrowsableProperties.Contains("Visible"))
        {
            var p = TypeDescriptor.GetProperties(this, true)["Visible"];
            properties.Add(TypeDescriptor.CreateProperty(
                this.GetType(), p, new[] { BrowsableAttribute.Yes }));
        }
        return new PropertyDescriptorCollection(properties.ToArray());
    }
    public bool Visible { get; set; }
    public override object GetPropertyOwner(PropertyDescriptor pd)
    {
        if (pd == null)
            return base.GetPropertyOwner(pd);
        else if (pd.Name == "Visible")
            return this;
        else
            return WrappedObject;
    }
}

Upvotes: 1

Related Questions