У меня есть класс, который отображается в сетке свойств. Одним из свойств является List<SomeType>
.
Какой простой/правильный способ настроить код, чтобы я мог добавлять и удалять элементы из этой коллекции через сетку свойств, предпочтительно используя стандартный CollectionEditor
.
Один из неправильных способов:
не вызывается при редактировании коллекции
Пользовательские аннакаты показывают, что я открываю интерфейс IEnumerable
вместо коллекции. Может кто-нибудь, пожалуйста, предоставьте мне более подробную информацию?
У меня есть дополнительное усложнение, которое коллекция, возвращаемая get
, фактически не указывает на член в моем классе, но создается на лету от другого члена, примерно так:
public List<SomeType> Stuff
{
get
{
List<SomeType> stuff = new List<SomeType>();
//...populate stuff with data from an internal xml-tree
return stuff;
}
set
{
//...update some data in the internal xml-tree using value
}
}
Это немного сложно. решение включает в себя построение с полной платформой .NET Framework (поскольку только клиентская инфраструктура не включает System.Design
). Вам нужно создать свой собственный подкласс CollectionEditor
и сообщить ему, что делать с временной коллекцией после того, как пользовательский интерфейс завершен с ним:
public class SomeTypeEditor : CollectionEditor {
public SomeTypeEditor(Type type) : base(type) { }
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) {
object result = base.EditValue(context, provider, value);
// assign the temporary collection from the UI to the property
((ClassContainingStuffProperty)context.Instance).Stuff = (List<SomeType>)result;
return result;
}
}
Затем вы должны украсить свое свойство с помощью EditorAttribute
:
[Editor(typeof(SomeTypeEditor), typeof(UITypeEditor))]
public List<SomeType> Stuff {
// ...
}
Длинный и запутанный, да, но он работает. После того, как вы нажмете "ОК" в всплывающем окне редактора коллекций, вы можете открыть его снова, и значения останутся.
Примечание. Необходимо импортировать пространства имен System.ComponentModel
, System.ComponentModel.Design
и System.Drawing.Design
.
Пока тип имеет открытый конструктор без параметров, он должен просто работать:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
class Foo {
private readonly List<Bar> bars = new List<Bar>();
public List<Bar> Bars { get { return bars; } }
public string Caption { get; set; }
}
class Bar {
public string Name { get;set; }
public int Id { get; set; }
}
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form {
Controls = { new PropertyGrid { Dock = DockStyle.Fill,
SelectedObject = new Foo()
}}});
}
}
get
- это только временная коллекция, созданная из других данных. Я отредактирую свой вопрос.