logo
03

Коллекции

Для сериализации свойств, которые являются коллекциями элементов, используйте атрибут DesignerSerializationVisibility со значением DesignerSerializationVisibility.Content. При этом у коллекции должен быть метод Add и/или AddRange, принимающий массив объектов и типизированный индексер. Дизайнер сериализует коллекции, используя этот метод, например, так:

this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.menuItem1 });

Тогда как в классе Menu:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]

public MenuItemCollection MenuItems

{

get

{

if (itemsCollection == null)

itemsCollection = new MenuItemCollection(this);

return itemsCollection;

}

}

В классе коллекции имеется:

public virtual void AddRange(MenuItem[] items)

{

if (items == null)

throw new ArgumentNullException("items");

for (int i = 0; i < items.Length; i++)

Add(items[i]);

}

Если вы не зададите собственный редактор для своей коллекции, то будет использован CollectionEditor, который вполне сносно редактирует простые коллекции. Тем не менее, он обладает рядом недостатков. В частности, CollectionEditor использует тип индексера для определения типа объекта, который он создает при нажатии кнопки Add. Изменить это очень просто, достаточно создать редактор, производный от CollectionEditor и переопределить один метод.

public class MyCollectionEditor : CollectionEditor

{

public MyCollectionEditor()

: base(typeof(MyCollection))

{}

protected override Type[] CreateNewItemTypes()

{

return new Type[] {typeof(MyItem1), typeof(MyItem2), typeof(MyItem3)};

}

}

Таким образом, вы сообщите редактору коллекций, что в вашей коллекции могут находиться элементы типа MyItem1, MyItem2 и MyItem3. Если вы возвращаете более одного типа, то редактор поместит рядом с кнопкой Add «стрелочку», нажав на которую пользователь сможет выбрать нужный тип. При нажатии на Add создаётся элемент самого первого типа в возвращаемом из CreateNewItemTypes() массиве. Помните, однако, что все типы, создаваемые редактором коллекций должны иметь конструктор без параметров.

После этого нужно сообщить дизайнеру, что ваша коллекция должна редактироваться именно этим редактором, используя атрибут:

[Editor(typeof(MyCollectionEditor), typeof(UITypeEditor))]

public MyCollection Items { get { ... } }

Такой атрибут можно поместить как на класс коллекции, чтобы все свойства такого типа редактировались вашим редактором, так и на конкретное свойство в конкретном классе.