Как я могу использовать WinForms PropertyGrid для редактирования списка строк?
В моем приложении есть сетка свойств, позволяющая пользователям изменять настройки. Это отлично работает для строк и других свойств значений, но сейчас мне нужен список строк, которые могут редактировать пользователи.
Проблема в том, что если у меня есть MyPropertyGrid.SelectedObject = new { Test = new List<string>() };
в моем коде, и пользователь пытается редактировать Test
свойства, когда они нажимают на кнопку Добавить, возникает следующая ошибка:
Constructor on type 'System.String' not found
Это имеет смысл, поскольку строки неизменны. Тем не менее, мне все еще нужен какой-то способ хранения нескольких строк (или строковых данных) в сетке свойств.
У кого-нибудь есть идеи, как мне это сделать?
3 ответа
Да, вы можете указать 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;
}
Сетка свойств для этого выглядит так:
Нажми на ...
и вы получите:
Если вам не нравится встроенный редактор коллекций, вы можете реализовать свой собственный редактор коллекций.
Мой пример показывает использование атрибута 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);
}
}
Вам не нужен сеттер на List<String>
потому что редактор коллекции не устанавливает это свойство, он просто добавляет или удаляет записи в свойстве. Так что просто предоставьте получатель.
Если вам нужен строковый контейнер, просто используйте: BindingList<string>
вместо list<string>
Редактор создается автоматически.
Кроме того, "кастинг" назад и вперед List<T>
это просто. От List до BindingList просто используйте bList = BindingList(orignalList)
конструктор (если вы получаете ошибку только для чтения - вставьте список один за другим). и чтобы получить список вы можете использовать .ToList()
метод расширения.
Объявление свойства пропускает один важный атрибут:[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
Без этого конструктор не сериализует сбор данных.