如何使用WinForms PropertyGrid编辑字符串列表?

在我的应用程序中,我有一个属性网格,允许用户更改设置。 这适用于字符串和其他值属性,但我现在需要的是一个可由用户编辑的字符串列表。

问题是如果我有MyPropertyGrid.SelectedObject = new { Test = new List() }; 在我的代码中,用户尝试编辑Test属性,当他们单击Add按钮时,会发生以下错误:

  Constructor on type 'System.String' not found 

这是有道理的,因为字符串是不可变的。 但是,我仍然需要一些方法来在属性网格中存储多个字符串(或类似字符串的数据)。

有没有人对如何实现这一点有任何想法?

是的,您可以在字符串列表中指定System.ComponentModel.Editor属性,并使用StringCollectionEditor作为编辑器 。 您需要向项目添加对System.Design.Dll的引用,以便进行编译。

例如,假设您的对象是这样的:

 [DefaultProperty("Name")] public class CustomObject { [Description("Name of the thing")] public String Name { get; set; } [Description("Whether activated or not")] public bool Activated { get; set; } [Description("Rank of the thing")] public int Rank { get; set; } [Description("whether to persist the settings...")] public bool Ephemeral { get; set; } [Description("extra free-form attributes on this thing.")] [Editor(@"System.Windows.Forms.Design.StringCollectionEditor," + "System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))] [TypeConverter(typeof(CsvConverter))] public List ExtraStuff { get { if (_attributes == null) _attributes = new List(); return _attributes; } } private List _attributes; } 

该属性网格如下所示:

在此处输入图像描述

点击...你会得到:

在此处输入图像描述

如果您不喜欢内置集合编辑器,则可以实现自己的自定义集合编辑器 。

我的示例显示了TypeConverter属性的使用。 如果不这样做 ,则列表在道具网格中显示为“(收集)”。 TypeConverter 将其显示为智能的东西 。 例如,要在属性网格中显示集合的短字符串表示forms,如下所示:

在此处输入图像描述

… TypeConverter是这样的:

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

您不需要List上的setter,因为集合编辑器不设置该属性,它只是添加或删除属性的条目。 所以只需提供吸气剂。

如果你只需要一个字符串容器,只需使用: BindingList而不是list

编辑器是自动创建的。

此外,在List来回“转换”很容易。 从List到BindingList只需使用bList = BindingList(orignalList)构造函数(如果你得到只读错误 – 逐个插入列表)。 要获取列表,您可以使用.ToList()扩展方法。

属性声明遗漏了一个重要属性: [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

没有它,设计师不会序列化收集数据。