Поставщики функций и соединительные элементы
Любой разрабатываемый объект в приложении Windows Presentation Foundation (WPF) или Silverlight может предоставлять произвольное число расширений конструктора. В следующем разделе обсуждаются возможности поставщиков функций и роль соединительных элементов в предоставлении возможностей разработки.
Общие сведения о поставщиках функций и соединительных элементах
Поставщик функций представляет собой примитивный тип, предоставляющий дополнительные возможности времени разработки для объекта. Некоторые поставщики функций могут просто предоставлять сведения о компонентах и не требуют никаких действий от имени данного конструктора. Другие поставщики функций могут добавлять элементы меню в контекстное меню конструктора объекта, создавать пользовательские графические элементы для изменения размера и редактирования или переопределять перетаскивание и удаление объектов в конструкторе.
Поставщики функций реализуются путем создания производного класса либо непосредственно от класса FeatureProvider, либо от класса, который является производным от FeatureProvider, например AdornerProvider и ContextMenuProvider. Поставщики функций разрабатывались легкими, они не должны пытаться сохранять состояние между экземплярами.
Соединительный элемент управляет одним или несколькими поставщиками функций для данного объекта. Соединительные элементы могут публиковать новые службы посредством поставщика служб и прослушивать события конструктора, таких как изменение выделения. Соединительные элементы реализуются посредством создания нового класса, производного от класса FeatureConnector<TFeatureProviderType> или PolicyDrivenFeatureConnector<TFeatureProviderType>.
Поставщики функций
Поставщик функций предназначен для того, чтобы служить простой точкой расширения. В наиболее распространенных сценариях, в которых используется расширение конструктора, гораздо удобнее получать производные классы от существующих классов поставщика функций вместо создания новых соединительных элементов. Поставщики функций не должны сохранять состояние, поскольку они создаются и уничтожаются много раз.
Поставщики функций полностью управляются соединительными элементами и связаны с объектом с помощью метаданных, а именно атрибута FeatureAttribute. Соединительный элемент обнаруживает типы FeatureProvider в этих метаданных. Класс FeatureManager определяет необходимые соединительные элементы для каждого обнаруженного поставщика функций.
Обычные реализации поставщика функций включают графические элементы выделения, команды и редакторы свойств. Дополнительные сведения см. в разделе Пошаговое руководство. Создание графического элемента времени разработки.
Примеры поставщиков функций
На следующем рисунке показан визуальный конструктор и типы функций, которые могут попадать в поставщик функций или категории соединительных элементов. Обратите внимание, что рисунок является только примером того, как могут быть реализованы некоторые возможности конструктора.
В следующей таблице перечислены поставщики функций, от которых можно получать производные классы.
Поставщик функций |
Описание |
---|---|
Добавляет графические элементы в область конструктора. |
|
Добавляет графические элементы, отображающиеся для основного выделенного объекта. |
|
Задает набор пунктов меню, отображаемых в контекстном меню. |
|
Задает набор пунктов меню, отображаемых для текущего выделенного элемента. |
|
PolicyDrivenFeatureConnector<TFeatureProviderType>.ItemFeatureProvider |
Определяет поставщики функций, которые принадлежат определенному элементу. |
Добавляет задачи к активному инструменту. |
|
Предоставляет набор задач, доступных при помощи инструмента выбора, когда класс находится в основном выделенном объекте. |
|
Фиксирует изменения свойств, внесенные пользователем в конструкторе, и предоставляет новые значения во время разработки. |
Создание поставщиков функций в режиме разработки
В большинстве случаев нет необходимости для создания собственного соединительного элемента. Можно создать поставщик функций и связать его непосредственно с классом при помощи атрибута FeatureConnectorAttribute. Класс FeatureManager является компонентом сред. Конструктор WPF, активирующим поставщиков функций. FeatureManager анализирует метаданные объекта, как только он помещается в рабочую область конструирования. При обнаружении атрибута FeatureConnectorAttribute для объекта создается связанный поставщик функций.
Например, если требуется создать графический элемент, позволяющий редактировать текст заголовка пользовательского элемента управления непосредственно на поверхности разработки, необходимо реализовать графический элемент, производный от класса PrimarySelectionAdornerProvider, который, в свою очередь, наследует от класса FeatureProvider. Далее необходимо связать пользовательский графический элемент с элементом управления с помощью атрибута FeatureConnectorAttribute.
Сопоставление поставщиков функций с типами
Средство разработки связывает поставщиков функций с типами через атрибуты метаданных. Должен существовать декларативный способ привязывания метаданных к объектам или экземплярам фактического времени выполнения. Эта привязка необходима на инструментальном уровне и не является обязанностью платформы разработки. На следующем рисунке показано, как средство времени разработки присоединяет поставщики функций к различным типам.
Существует два способа привязки поставщиков функций к типами в архитектуре сред. Конструктор WPF: типы FeatureAttribute и FeatureConnectorAttribute. Тип FeatureAttribute используется для типов или экземпляров редактируемых объектов и обеспечивает свойство, представляющее класс FeatureProvider.
Тип FeatureConnectorAttribute принадлежит классу FeatureProvider и указывает, какой тип соединительного элемента необходим для размещения указанного поставщика функций. Класс FeatureManager создает необходимые экземпляры FeatureConnector<TFeatureProviderType> при изменении объектов, которые передаются в него.
Рассмотрим конструктор, определенный для WPF, в котором редактируемые объекты принадлежат типу UIElement. Такой инструмент может использовать одну или несколько "скоб захвата" для прорисовки границ отдельных элементов. Эти графические элементы визуально представляют выделенный объект и позволяют работать с этими редактируемыми объектами. Конструктор связывает функцию скобы захвата со всеми объектами типа UIElement при помощи метаданных. На следующем рисунке показано, как конструктор может присоединять поставщик скобы захвата к типу UIElement на поверхности разработки.
Если тип UIElement существует и передается диспетчеру функций для анализа, поставщик GrabHandleProvider обнаруживается с помощью метаданных, связанных с типом UIElement. Сам тип GrabHandleProvider или его базовый тип просматривается с помощью метаданных для определения требуемого соединительного элемента.
Соединительные элементы
Соединительные элементы являются самым нижним уровнем расширения среды, предоставляемым данной архитектурой. Соединительные элементы создаются с заданной ссылкой на EditingContext. Соединительные элементы могут подписываться на глобальные службы и могут добавлять свои собственные службы. Абстрактный класс FeatureConnector<TFeatureProviderType> реализует интерфейс IDisposable, который осуществляет стратегию простой очистки.
Соединительные элементы создаются по запросу. Когда FeatureManager обнаруживает тип FeatureConnectorAttribute для класса FeatureProvider, создается указанный класс FeatureConnector<TFeatureProviderType>, если его тип еще не существует. Соединительные элементы создаются только при их обнаружении, при запуске не создается значение по умолчанию. Если есть несколько типов FeatureConnectorAttribute для FeatureProvider, инициализируются все соединительные элементы. Это позволяет элементам сторонних производителей наследовать от существующего класса FeatureProvider, добавлять пользовательский соединительный элемент и инициализировать оба набора функций.
Большинство функциональных возможностей класса FeatureConnector<TFeatureProviderType> реализовано в защищенном методе CreateFeatureProviders. При передаче объекта в этот метод функциональный соединитель ищет в нем атрибуты FeatureAttribute. Если эти атрибуты найдены, создается экземпляр FeatureProvider, связанный с каждым атрибутом, и возвращается в списке.
Базовый класс FeatureConnector<TFeatureProviderType> является универсальным и принимает тип поставщика функций, который размещает FeatureConnector<TFeatureProviderType>. Поставщики функций используют тип FeatureConnectorAttribute для указания соответствующего соединительного элемента. Защищенные методы базового класса FeatureConnector<TFeatureProviderType>, главным образом метод CreateFeatureProviders, могут возвращать типизированные коллекции поставщиков функций производным соединительным элементам; при этом в производных классах не возникает проблем относительно приведения и безопасности типов.
Создание пользовательских соединительных элементов
Если требуется прослушивать события конструктора, такие как выбор, необходимо создать свой собственный соединительный элемент. Создайте класс, производные от класса FeatureConnector<TFeatureProviderType> или PolicyDrivenFeatureConnector<TFeatureProviderType>, для реализации пользовательской логики конструктора.
Соединительные элементы предоставляют ссылки на глобальный контекст EditingContext конструктора, через который соединительный элемент может получать доступ к службам конструктора, а также публиковать свои собственные пользовательские службы. Например, поставщику элемента управления "диаграмма" может потребоваться опубликовать службу, позволяющую пользовательскому редактору типов в конструкторе перечислять все точки, находящиеся в настоящее время на диаграмме.
После создания класса, производного от класса FeatureConnector<TFeatureProviderType>, можно связать его с поставщиком функций, применяя атрибут FeatureConnectorAttribute к поставщику функций. Каждый раз, когда создается экземпляр этого поставщика функций, диспетчер FeatureManager проверяет метаданные на наличие атрибута FeatureConnectorAttribute. Если этот атрибут определен и экземпляр соответствующего класса FeatureConnector<TFeatureProviderType> не запущен в настоящий момент, диспетчер FeatureManager создаст его и свяжет все будущие экземпляры этого поставщика функций с классом FeatureConnector<TFeatureProviderType>.
Пример кода, демонстрирующий способы реализации соединительного элемента, см. в разделе Практическое руководство. Создание пользовательского соединительного элемент.