How can I use a WinForms PropertyGrid to edit a list of strings?
Asked Answered
D

3

23

In my application I have a property grid to allow users to change settings. This works fine for strings and other value properties, but what I need now is a list of strings that can be edited by users.

The problem is that if I have MyPropertyGrid.SelectedObject = new { Test = new List<string>() }; in my code and the user attempts to edit the Test property, when they click on the Add button, the following error occurs:

 Constructor on type 'System.String' not found

This makes sense as strings are immutable. However, I still need some way to store multiple strings (or string-like data) in a property grid.

Does anyone have any ideas on how I can accomplish this?

Denn answered 10/6, 2011 at 13:27 Comment(2)
Try this, MyPropertyGrid.SelectedObjec = Test //it'll return string list on button click set the string list in the Test property....Policewoman
I'm not sure what you mean to try, as it looks like your code got eaten up by the commenting format.Denn
T
53

Yes, you can specify an System.ComponentModel.Editor attribute on your list of strings, with StringCollectionEditor as the editor. You need to add a reference to System.Design.Dll to your project, in order for this to compile.

Example, suppose your object is like this:

[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;
}

The property grid for that looks like this:

enter image description here

Click on the ... and you get:

enter image description here

If you don't like the builtin collection editor, you can implement your own custom collection editor.

My example shows the use of a TypeConverter attribute. If you don't do that, then the list displays in the prop grid as "(Collection)". The TypeConverter gets it to display as something intelligent. For example, to display a short string representation of the collection in the property grid, like this:

enter image description here

...the TypeConverter is like this:

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);
    }
}

You don't need a setter on the List<String>, because the collection editor doesn't set that property, it merely adds or removes entries to the property. So just provide the getter.

Tours answered 10/6, 2011 at 15:35 Comment(2)
Awesome, the first method works like a charm (The string collection editor should work fine for my needs). Much appreciated :)Denn
Excellent answer !Kaluga
H
11

If you just need a string container just use: BindingList<string> instead of list<string>

The editor is created automatically.

Also, "casting" back and forth to List<T> is easy. From List to BindingList just use the bList = BindingList(orignalList) constructor (if you get read only error - insert the list one by one). and to get the list you can use the .ToList() extension method.

Hyperphysical answered 23/11, 2013 at 10:10 Comment(0)
H
3

Property declaration misses one important attribute: [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

Without it designer does not serialize collection data.

Heliotype answered 24/4, 2013 at 10:26 Comment(1)
It works without the attribute if you use a binding list, ie, BindingList<string>Hamburg

© 2022 - 2024 — McMap. All rights reserved.