【问题标题】:Use a custom editor in a PropertyGrid for a type I cannot modify在 PropertyGrid 中为我无法修改的类型使用自定义编辑器
【发布时间】:2025-12-11 21:40:02
【问题描述】:

在我的应用程序中,我有一个对象,它是我想使用 PropertyGrid 编辑的属性。对于大多数属性,这工作正常。现在这个对象包含一个List<string> 类型的属性。编辑此属性时出现错误,因为 string 没有合适的构造函数。

基本上这与this question中描述的情况相同。

不幸的是,我不能从那里使用answer,因为我不能修改我的对象的代码,所以不能将Editor 属性应用于属性。还有其他方法可以在这里使用自定义编辑器吗?

【问题讨论】:

  • PropertyGrid 使用类型描述符,它不依赖于反射。因此,您无需将 Editor 添加到属性本身。为类提供合适的类型描述符就足够了。您可以在运行时将Editor 应用于属性,方法是在运行时为类提供新的类型描述符。

标签: c# .net winforms propertygrid


【解决方案1】:

由于您无法更改类的代码,您可以在运行时为您的类注册一个新的类型描述符以提供自定义类型描述。

使用AssociatedMetadataTypeTypeDescriptionProvider,您可以为您的类创建一个类型描述符提供程序,该提供程序使用元数据类来提供类型描述。然后你可以使用TypeDescriptor.AddProvider注册提供者。

示例

假设你不能更改其代码的类是这样的:

public class MyClass
{
    public MyClass()
    {
        List = new List<string>();
    }
    public string Name { get; set; }
    public List<string> List { get; set; }
}

要解决这个问题,你应该定义另一个具有相同属性的类,并用你喜欢的属性装饰这些属性,包括编辑器和转换器属性:

public class MyClassMetadata
{
    [DisplayName("Name Property")]
    public string Name { get; set; }

    [Editor(@"System.Windows.Forms.Design.StringCollectionEditor," +
        "System.Design, Version=2.0.0.0, Culture=neutral, " + 
        "PublicKeyToken=b03f5f7f11d50a3a",
        typeof(System.Drawing.Design.UITypeEditor))]
    public List<string> List { get; set; }
}

然后在显示原始类之前,为原始类注册一个新的类型描述符提供程序,它使用我们创建的元数据类返回元数据:

private void Form1_Load(object sender, EventArgs e)
{
    var provider = new AssociatedMetadataTypeTypeDescriptionProvider(typeof(MyClass),
        typeof(MyClassMetadata));
    TypeDescriptor.AddProvider(provider, typeof(MyClass));
    this.propertyGrid1.SelectedObject = new MyClass();
}

我想您已经拥有来自first linkCsvConverter

public class CsvConverter : TypeConverter
{
    // Overrides the ConvertTo method of TypeConverter.
    public override object ConvertTo(ITypeDescriptorContext context,
       CultureInfo culture, object value, Type destinationType)
    {
        List<String> v = value as List<String>;
        if (destinationType == typeof(string))
        {
            return String.Join(",", v.ToArray()); 
        }
        return base.ConvertTo(context, culture, value, destinationType);
    }
}

【讨论】:

  • 您可以在this post 中查看分步示例。