C# PropertyGrid => How to change visible Properties at Runtime

前端 未结 2 1799
野趣味
野趣味 2021-01-28 00:32

I have to following problem,

In a map-editor you can place \"Joints\" (FarseerPhysics) on objects, there are 23 types of joints (in an enum). The joints are all pretty m

相关标签:
2条回答
  • 2021-01-28 01:05

    There is no simple to use built-in support in PropertyGrid for dynamically altering which properties are visible depending on the value of another property. This doesn't mean it can't be done, just that it takes a bit of work.

    As you've already discovered, what controls whether a property is visible or not is the BrowsableAttribute. So basically you need to change this attribute dynamically, and the way to do that is to create your own TypeProvider and TypeDescriptor for your class, that dynamically returns the Browsable(false) or Browsable(true) attribute for the property to be hidden/shown depending on the value of another property in the class. I will not attempt to describe how TypeProvider and TypeDescriptor works here, since it is quite a lengthy subject and there is much information readily available on this subject on the web already.

    In addition you need to specify the [RefreshProperties(RefreshProperties.All)] attribute on the property controlling whether another property should be visible or not. This will force the propertygrid to requery the TypeDescriptor for the list of properties whenever its value is changed, giving your TypeDescriptor the chance to return a different set of properties, or different attributes on the properties it returns.

    I hope this at least points you in the right direction. Unfortunately it takes a quite bit of work to glue these things together.

    0 讨论(0)
  • 2021-01-28 01:05

    Here is a method for changing the Browsable attribute of a property in your JointItem class:

    private void ChangeBrowsability(object pThis, string pProperty, bool pBrowsable)
    {
        PropertyDescriptor pdDescriptor = TypeDescriptor.GetProperties(pThis.GetType())[pProperty];
        BrowsableAttribute baAttribute = (BrowsableAttribute)pdDescriptor.Attributes[typeof(BrowsableAttribute)];
        FieldInfo fiBrowsable = baAttribute.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
        fiBrowsable.SetValue(baAttribute, pBrowsable);
    }
    

    Then you could have a big long if then else sequence or the likes:

    JointItem jiThis = WhereEverYouGetYourJointItemFrom();
    if (jiThis.JointType == eJoinType.Elbow)
    {
        ChangeBrowsability(jiThis, "JointAngle", true);
        ChangeBrowsability(jiThis, "MinAngle", true);
        ChangeBrowsability(jiThis, "MaxAngle", true);
        ChangeBrowsability(jiThis, "ScrewType", false);
        //...
    }
    else ...
    

    Of course you need your dose of "using"s!

    using System.ComponentModel;
    using System.Reflection;
    
    0 讨论(0)
提交回复
热议问题