【问题标题】:Changing the browsability of a property at runtime在运行时更改属性的可浏览性
【发布时间】:2021-10-18 15:00:30
【问题描述】:

我的 winforms 应用程序中有一个 PropertyGrid,它显示了一些选定对象的属性。我希望有时会显示某个属性,而有时则不会,由我选择,(假设每次在运行时按下特定按钮时,可浏览性都会发生变化)。 在运行前设置可浏览性非常容易,使用 BrowsableAttribute,据我了解,属性是在设计时设置的,因此我需要另一个解决方案。 在很多地方我都找到了这段代码:

public static void ChangeBrowsability(SomeObject obj, string propertyName, bool isBrowsable)
{//usage: supposed to change browsability at runtime
        PropertyDescriptor descriptor = TypeDescriptor.GetProperties(obj)[propertyName];
        BrowsableAttribute attrib = (BrowsableAttribute)descriptor.Attributes[typeof(BrowsableAttribute)];
        FieldInfo browsableField = attrib.GetType().GetField("browsable", BindingFlags.NonPublic | BindingFlags.Instance);
        browsableField.SetValue(attrib, isBrowsable);
}

第一个问题是 browsableField 出于某种原因总是为空,我想知道为什么。 也欢迎使用此代码的替代解决方案。

【问题讨论】:

  • 属性信息存储在元数据中,并在编译时编译到程序集中
  • 重复:onetwothree 等...
  • 您可以为您的类实现一个 TypeConverter 并通过覆盖 GetProperties 方法返回您想要的任何属性。您不必使用 BrowsableAttribute。你可以得到一些提示here

标签: c# .net winforms


【解决方案1】:

您无法更改属性定义的现实 - 它们被烘焙到 IL 中;但是,您可以撒谎和作弊。 winforms PropertyGrid 不直接进入反射 - 它使用通过TypeDescriptor 的间接路由,TypeDescriptor 默认 使用反射。但是,您可以实现自己的描述符实现,改变一切,特别是(对于这种情况):PropertyDescriptor.IsBrowsable。这是个好消息。

这是困难的坏消息。喜欢; 真的很难;你必须真的,真的关心这个功能才能使用它。它涉及:

  • 捕获基于反射的传出ICustomTypeDescriptor,因此您可以将其用作基础
  • 实现您自己的ICustomTypeDescriptor,将属性公开为“装饰器”
  • 注册一个TypeDescriptionProvider 以公开您自己的类型描述符
  • 捕获基于反射的传出PropertyDescriptorCollection,以便您可以将它们用作基础
  • 实现您自己的 PropertyDescriptors 装饰器,转发大部分 API,除了 IsBrowsable 您可以添加自己的逻辑

可行,但是:非常复杂和令人费解,而且老实说:使用的 API 基本上已经过时并且十年来从未见识过。一个工作示例很容易遇到数百行 C#,因此超出了我可以在此处合理提供的范围。

【讨论】:

  • 谢谢,那么有什么替代方案?
  • @Mayerstro 替代:docs.microsoft.com/en-us/dotnet/api/… - 使用它,并指定指示不同场景中可浏览性的 alternative 属性,并相应地注释您的类型
  • @Mayerstro 我不明白这个问题;你能澄清一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-14
  • 2011-09-20
相关资源
最近更新 更多