Подтвердить что ты не робот

Как я могу использовать WinForms PropertyGrid для редактирования списка строк?

В моем приложении у меня есть сетка свойств, позволяющая пользователям изменять настройки. Это отлично работает для строк и других свойств значения, но теперь мне нужен список строк, которые могут редактировать пользователи.

Проблема в том, что если у меня есть MyPropertyGrid.SelectedObject = new { Test = new List<string>() }; в моем коде, и пользователь пытается изменить свойство Test, когда они нажимают кнопку "Добавить", возникает следующая ошибка:

 Constructor on type 'System.String' not found

Это имеет смысл, поскольку строки неизменяемы. Тем не менее, мне все еще нужен способ хранения нескольких строк (или данных, подобных строкам) в сетке свойств.

Есть ли у кого-нибудь идеи о том, как я могу это сделать?

4b9b3361

Ответ 1

Да, вы можете указать атрибут 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;
}

Сетка свойств для этого выглядит так:

enter image description here

Нажмите ..., и вы получите:

enter image description here

Если вам не нравится встроенный редактор коллекций, вы можете реализовать собственный редактор собственных коллекций.

В моем примере показано использование атрибута TypeConverter. Если вы этого не сделаете, список отобразится в сетке прокрутки как "(Коллекция)". TypeConverter выводит его как нечто интеллектуальное. Например, чтобы отобразить короткое строковое представление коллекции в сетке свойств, например:

enter image description here

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

Вам не нужен сеттер в List<String>, потому что редактор коллекции не устанавливает это свойство, он просто добавляет или удаляет записи в свойство. Так что просто предоставляйте геттер.

Ответ 2

Если вам просто нужен контейнер строк, используйте: BindingList<string> вместо list<string>

Редактор создается автоматически.

Кроме того, "отливка" назад и вперед на List<T> проста. Из списка в BindingList просто используйте конструктор bList = BindingList(orignalList) (если вы получаете только ошибку чтения - вставляйте список один за другим). и для получения списка вы можете использовать метод расширения .ToList().

Ответ 3

Объявление свойства пропускает один важный атрибут: [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

Без этого дизайнер не сериализует данные коллекции.