1

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);
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Tuguldur
  • 31
  • 5
  • 1
    Hi. Please show us some code that you tried so we can help you with your solution – Cornel Raiu Jul 17 '19 at 07:41
  • Sounds like you need dynamic properties, see [PropertyDescriptor](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.propertydescriptor), you will have to create custom property descriptor. Not sure what exactly logic you want: not changing visibility upon changing `Visibility` property, but somehow else? How? What happens on save? Can you call a method of control? Set another property? Or you want all controls to subscribe to some even which will trigger their visibility check? – Sinatr Jul 17 '19 at 08:02
  • The program I am making has something like "edit mode" and has a lot of forms, user can launch form in edit mode to edit text, backcolor, forecolor, ... etc and when saved changes would be written to DB. And when in "normal mode", form gets property changes from DB and changes it's properties value. To edit any control, user must see every controls in form even though they are hidden otherwise hidden control would be gone forever for user. And user might want to show hidden textBox after hiding it. – Tuguldur Jul 17 '19 at 08:11
  • Generally, I need something to indicate that the control is hidden. – Tuguldur Jul 17 '19 at 08:28

1 Answers1

1

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;
    }
}
Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • 1
    Probably too late for you, but hope you are able how it works in action and verify it; however I've already tested and it works perfectly! – Reza Aghaei Jan 21 '21 at 20:47
  • You may also be interested to this [post](https://stackoverflow.com/a/40209045/3110834). – Reza Aghaei Jan 21 '21 at 20:59