C#PropertyGrid =>如何在运行时更改可见属性

时间:2011-09-09 09:32:22

标签: c#

我必须关注问题,

在地图编辑器中,您可以在对象上放置“关节”(FarseerPhysics),有23种类型的关节(在枚举中)。关节几乎相同(每种关节类型只有1-2个新属性)。我想让用户使用WinForm PropertyGrid更改关节。 因此,如果用户更改属性“JointType”(枚举),PropertyGrid需要隐藏旧属性并显示新属性,有没有办法实现这一点? (所有关节的所有属性都保存在一个名为JointItem的类中,我只需要动态显示/隐藏其中一些)

2 个答案:

答案 0 :(得分:3)

PropertyGrid中没有简单易用的内置支持,可根据另一个属性的值动态更改哪些属性可见。这并不意味着它无法完成,只需要做一些工作。

正如您已经发现的那样,控制属性是否可见的是BrowsableAttribute。所以基本上你需要动态更改这个属性,这样做的方法是为你的类创建自己的TypeProviderTypeDescriptor,动态返回Browsable(false)或{{1}根据类中另一个属性的值隐藏/显示属性的属性。我不会试图描述Browsable(true)TypeProvider如何在这里工作,因为它是一个相当漫长的主题,并且已经有很多关于此主题的信息已经在网上提供。

此外,您需要在属性上指定TypeDescriptor属性,以控制是否应显示其他属性。这将强制propertygrid在其值更改时重新查询属性列表的[RefreshProperties(RefreshProperties.All)],从而使TypeDescriptor有机会返回不同的属性集,或者返回它返回的属性的不同属性。

我希望这至少能指出你正确的方向。不幸的是,将这些东西粘合在一起需要花费很多工作。

答案 1 :(得分:0)

这是一种用于更改JointItem类中的属性的Browsable属性的方法:

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);
}

然后,如果没有其他序列或类似内容,您可能会很长:

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 ...

您当然需要“使用”剂量!

using System.ComponentModel;
using System.Reflection;