Changing Browsable Attribute at Runtime (C#)
Asked Answered
A

3

8

I'm trying to change the Browsable attribute of a variable in one of my classes at runtime. The class containing the attribute looks like this:

public class DisplayWallType : WallType
    {
        [TypeConverter(typeof(SheathingOptionsConverter))]
        [Browsable(false)]
        public override Sheathing SheathingType { get; set; }

        public DisplayWallType(string passedName, string passedType, bool passedMirrorable, Distance passedHeight, string passedStudPattern, Distance passedStudSpacing, VaporBarrier passedBarrier)
            : base(passedName, passedType, passedMirrorable, passedHeight, passedStudPattern, passedStudSpacing, passedBarrier)
        {

        }

        /// <summary>
        /// Empty constructor for XML serialization
        /// </summary>
        public DisplayWallType()
        {

        }
    }

I initially set it to false for SheathingType because I don't want that attribute to show up in the first form of my application. However, I do want it visible in my second form so I have this method to change it

private void _makeSheathingVisible(DisplayWallType wallTypeToMakeSheathingVisible)
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(wallTypeToMakeSheathingVisible.GetType())["SheathingType"];
            BrowsableAttribute attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
            FieldInfo isBrow = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
            isBrow.SetValue(attrib, true);
        }

That method above takes a DisplayWallType object and ensures that Browsable is set to true. My second form is a treeview combined with a property grid. The treeview is populated with instances of DisplayWallType and when one is selected, it is passed into that method so that SheathingType shows up in the PropertiesGrid with the rest of the properties from the parent class.

enter image description here

However, SheathingType still does not show up as a property so something is wrong with my approach but I have no idea what

Ararat answered 9/7, 2015 at 15:16 Comment(1)
You can't use declarative attributes, they're carved in stone. You can check my answer here for a full dynamic property descriptor: #18926609Distraint
S
3

RefreshPropertiesAttribute Class Indicates that the property grid should refresh when the associated property value changes.

    [TypeConverter(typeof(SheathingOptionsConverter))]
    [Browsable(false)] // changes at runtime
    public override Sheathing SheathingType { get; set; }

    private bool updateWhenChanged;

    [RefreshProperties(RefreshProperties.All)]
    public bool UpdateWhenChanged 
    {
        get => updateWhenChanged;
        set
        {
            if (updateWhenChanged != value)
            {
                SetBrowsableAttributeValue(nameof(SheathingType), value);

                updateWhenChanged = value;
            }
        }
    }

    private void SetBrowsableAttributeValue(string attribute, object value)
    {
        var descriptor = TypeDescriptor.GetProperties(GetType())[attribute];
        var attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
        // var isBrow = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance); // Works only for framework
        var isBrow = attrib.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault(a => a.Name.Contains("browsable", StringComparison.OrdinalIgnoreCase));
        isBrow.SetValue(attrib, value);
    }
Snout answered 19/8, 2020 at 9:41 Comment(0)
H
1

You cannot get Browsable attribute for one exact property except you have its TypeDescriptor explicit declaration. In your case GetField("browsable") will return FieldInfo for all properties and will switch them to visible true. The same thing will appear if you have some properties and set one browsable to false - it will hide all properties.

Provide a custom TypeDescriptor for needed attributes or use some solutions like https://www.codeproject.com/articles/7852/propertygrid-utilities.

Hatti answered 8/12, 2016 at 9:35 Comment(0)
K
1

I know this issue is from some time ago, but I fixed the same issue today by calling propertiesGrid.Refresh() after changing the Browsable attribute. Maybe it helps someone in the future.

Kernan answered 18/2, 2019 at 14:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.