Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing Browsable Attribute at Runtime (C#)

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

like image 438
Nick Gilbert Avatar asked Jul 09 '15 15:07

Nick Gilbert


3 Answers

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);
        isBrow.SetValue(attrib, value);
    }
like image 131
Andrei Krasutski Avatar answered Oct 24 '22 10:10

Andrei Krasutski


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.

like image 1
Andark Avatar answered Oct 24 '22 11:10

Andark


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.

like image 1
hvk Avatar answered Oct 24 '22 12:10

hvk