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

Kal*_*exx 20 c# string propertygrid winforms

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

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

 Constructor on type 'System.String' not found
Run Code Online (Sandbox Code Playgroud)

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

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

Che*_*eso 46

是的,您可以使用编辑器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<String> ExtraStuff
    {
        get
        {
            if (_attributes == null)
                _attributes = new List<String>();
            return _attributes;
        }
    }
    private List<String> _attributes;
}
Run Code Online (Sandbox Code Playgroud)

该属性网格如下所示:

在此输入图像描述

点击即可...获得:

在此输入图像描述

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

我的示例显示了TypeConverter属性的使用.如果不这样做,则列表在支柱网格中显示为"(收集)".TypeConverter 让它显示为智能的东西.例如,要在属性网格中显示集合的短字符串表示形式,如下所示:

在此输入图像描述

... TypeConverter是这样的:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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


Guy*_*y L 7

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

编辑器是自动创建的.

而且,来回"铸造" List<T>很容易.从List到BindingList只需使用bList = BindingList(orignalList)构造函数(如果你得到只读错误 - 逐个插入列表).并获取列表,您可以使用.ToList()扩展方法.