logo
03

Коллекции элементов

Если контрол должен содержать в себе некий набор элементов, создайте классы, представляющие эти элементы, а также типизированные коллекции для их хранения. Контрол должен получать уведомления об изменениях в составе и свойствах элементов, чтобы он мог изменить своё представление адекватно состоянию. Для этого создайте в контроле специальный internal-метод, вызываемый из коллекций и их элементов при изменении состояния. Можно, конечно, использовать события и делегаты, но в данном случае это не особенно оправдано из соображений производительности, а клиенты таких сообщений заранее известны. Наследуйте коллекции от CollectionBase, переопределите методы OnClear, OnInsert, OnRemove, OnSet для того, чтобы уведомлять контрол об изменениях в составе коллекций. Определите типизированные Insert, Add, Remove, IndexOf, AddRange и индексер. Если контрол достаточно сложен, подумайте о специализированных методах, которые принимают во внимание произведенное изменение, а не используют универсальный метод вроде SomethingChangedUpdateAll.

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

Довольно часто требуется произвести некоторые вычисления извне контрола или воздействовать на контрол из кода. Предоставьте полезные методы для таких случаев, например, такие:

public ItemType GetItemAt(Point pt);

public ItemType GetItemAt(int x, int y);

public Rectangle GetItemRect(ItemType item);

public void EnsureVisible(ItemType item);

Предоставляйте отдельный виртуальный защищенный метод для отрисовки элемента. В качестве параметров, кроме собственно элемента, используйте Graphics и Rectangle. Рассмотрите необходимость ограничить область рисования путём установки Graphics.Clip. Обратите внимание на отрисовку частично видимых элементов.

protected virtual void DrawItem(Graphics g, ItemType item, Rectangle rect);