PropertyGrid - 显示特定接口的属性,而不是所有属性

PropertyGrid - Show properties of a specific Interface, not all properties

我目前正面临 PropertyGrid 的(恕我直言)奇怪行为:

我有一个定义了一些属性的接口 (ITest)。该接口将由 ComponentPanel (TestImpl) 实现。另一部分是一个 Component (TestComponent) 有一个 public 属性 的接口类型。默认实现将分配给 属性 并且用户可以将其更改为更具体的实现。如果我将此 TestComponent 添加到 Form,我希望通过扩展 public-interface-属性,只有接口中声明的属性是可见的 -相反 PanelComponent 的所有属性都是可见的...

public interface ITest
{
    string AAAAA { get; set; }
}

public class TestImpl: Panel, ITest
{
    public string AAAAA { get; set; }
}

public class TestComponent : Component
{
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public ITest Obj { get; set; }
    public TestComponent()
    {
        Obj = new TestImpl();
    }
}

// To reproduce create a simple Form, add a PropertyGrid, create and assign the TestComponent
public partial class Form4 : Form
{
    public Form4()
    {
        InitializeComponent();

        var comp = new TestComponent();
        comp.Obj.AAAAA = "Some Text";

        propertyGrid1.SelectedObject = comp;
    }
}

有没有办法只显示接口属性?

PropertyGrid 默认显示控件的所有 public 可浏览属性的显示名称。它使用您的对象的 TypeDescriptor 来询问其元数据,包括其可浏览的属性及其显示名称。

要自定义此行为,您需要为您的对象注册一个新的 TypeDescriptionProvider

例子

在下面的示例中,我创建了一个派生自 Panel 并实现 IMyInterfaceMyPanel 控件。然后我创建了一个自定义 MyTypeDescriptionProvider<T> 并将 MyTypeDescriptionProvider<IMyInterface> 设置为我的控件的 TypeDescriptionProvider

这样,当您将 MyPanel 的实例设置为 PropertyGridSelectedObject 时,只有 IMyInterface 的属性将显示在 PropertyGrid 中.

using System;
using System.ComponentModel;
using System.Windows.Forms;

public interface IMyInterface
{
    string MyProperty1 { get; set; }
    string MyProperty2 { get; set; }
}

public class MyTypeDescriptionProvider<T> : TypeDescriptionProvider
{
    public MyTypeDescriptionProvider() : base(TypeDescriptor.GetProvider(typeof(T))) { }

    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
        object instance)
    {
        return base.GetTypeDescriptor(typeof(T), instance);
    }
}

[TypeDescriptionProvider(typeof(MyTypeDescriptionProvider<IMyInterface>))]
public class MyPanel : Panel, IMyInterface
{
    public string MyProperty1 { get; set; }
    public string MyProperty2 { get; set; }
}

注意: 作为重要说明,请记住此类功能对设计时根本没有用。因为在设计时,您需要在设计器中的 PropertyGrid 中显示控件的属性,并且您需要让设计器知道这些属性以便能够为它们序列化值。