Question

I am binding a properties Grid to a bunch of custom Objects that are being written by other developers. These objects are constantly being changed and updated, so they include properties that just throw NotImplemented Exceptions. Sometimes they include properties like

[Obsolete("use thingy instead to get other thing", true)]

Instead of annoying the other developers. with things that I know will be changed later. What can I do to make sure my properties Grid doesn't break on those specific properties?

Thanks for the help. the other Developers appreciate it ;)

Was it helpful?

Solution

I imagine that you are trying to bind the PropertyGrid to the objects at runtime, not in the designer. If you mean the propertygrid in the winform designer, the answer would be different, and you should look at the postFilterEvents method of ControlDesigner.

The simplest solution would be to set the BrowsableAttribute to false for the properties that you want to hide. This means that when the other developers add the ObsoleteAttribute, they should add [Browsable(false)], too. But I understand that you'd like something more "automatic". You could write a method that changes the browsable attributes of the properties of an object before passing it to the PropertyGrid. This can be done getting the TypeDescriptor for each property, then getting its BrowsableAttribute, and setting its value according to the fact that there is an ObsoleteAttribute, or that it throws an exception (this has to be done via reflection, since browsable is private). The code could be something like this:

    private static void FilterProperties(object objToEdit)
    {
        Type t = objToEdit.GetType();
        PropertyInfo[] props = t.GetProperties();
        // create fooObj in order to have another instance to test for NotImplemented exceptions 
        // (I do not know whether your getters could have side effects that you prefer to avoid)
        object fooObj = Activator.CreateInstance(t);
        foreach (PropertyInfo pi in props)
        {
            bool filter = false;
            object[] atts = pi.GetCustomAttributes(typeof(ObsoleteAttribute), true);
            if (atts.Length > 0)
                filter = true;
            else
            {
                try
                {
                    object tmp = pi.GetValue(fooObj, null);
                }
                catch
                {
                    filter = true;
                }
            }
            PropertyDescriptor pd = TypeDescriptor.GetProperties(t)[pi.Name];
            BrowsableAttribute bAtt = (BrowsableAttribute)pd.Attributes[typeof(BrowsableAttribute)];
            FieldInfo fi = bAtt.GetType().GetField("browsable",
                               System.Reflection.BindingFlags.NonPublic |
                               System.Reflection.BindingFlags.Instance);
            fi.SetValue(bAtt, !filter);
        }
    }

This should work, but it's got a limit. There must be at least a BrowsableAttribute in the class you are editing (it doesn't matter if it's set to true or false), otherwise the PropertyGrid will always be empty.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top