Поделиться через


Пошаговое руководство. Добавление смарт-тегов в компонент Windows Forms

Смарт-теги — это элементы пользовательского интерфейса в виде меню, которые предоставляют часто используемые во время разработки параметры. Большинство стандартных компонентов и элементов управления, доступных в платформе .NET Framework, содержат улучшения смарт-тегов и команд конструктора. Процедуры в данном пошаговом руководстве показывают, как добавлять поддержку смарт-тегов в компоненты и элементы управления.

Смарт-теги можно добавить в компоненты Window Forms для предоставления часто используемых во время разработки параметров. Элементы в области смарт-тега логически сгруппированы по категориям, а индивидуальные реализации DesignerActionMethodItem при необходимости могут быть дублированы как записи команд конструктора. Множество стандартных компонентов и элементов управления, доступных в платформе .NET Framework, содержат улучшения смарт-тегов и команд конструктора. Разработчики компонентов и пользовательских элементов управления также могут добавлять поддержку смарт-тегов; обычно это выполняется с помощью модели внедрения.

Добавление смарт-тегов с использованием модели внедрения требует добавления в проект компонента следующих элементов:

  • Реализация класса, производного от DesignerActionList, который определяет методы и свойства, являющиеся целевыми для элементов меню смарт-тегов. Данный класс также предоставляет переопределенный метод GetSortedActionItems, возвращающий массив экземпляров DesignerActionItem.

  • Класс конструктора, связанный с компонентом, должен выполнять реализацию свойства ActionLists. Получение этого свойства предоставляет DesignerActionListCollection, которая содержит все экземпляры DesignerActionList, связанные с отдельным меню смарт-тега. Часто в такой коллекции содержится всего один список.

Примечание

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

В следующей процедуре описываются способы добавления смарт-тегов при помощи кода из простого примера элемента управления ColorLabel, который является производным от стандартного элемента управления Label Windows Forms. С этим элементом управления связан конструктор ColorLabelDesigner.

Сведения о том, как скопировать весь текст кода из этой темы, см. в разделе Практическое руководство. Вложение смарт-тегов в компонент Windows Forms.

Обязательные компоненты

Для выполнения этого пошагового руководства потребуется следующее.

  • разрешения, необходимые для создания и выполнения проектов приложений Windows Forms на компьютере, на котором установлена платформа .NET Framework.

Реализация класса, производного от DesignerActionList

  1. В пространстве имен, к которому относится компонент, добавьте объявление класса, производного от DesignerActionList.

    Примечание

    Необходимо добавить ссылку на сборку времени разработки — System.Design.dll.Эта сборка не входит в клиентский профиль платформы .NET Framework 4.Чтобы добавить ссылку на сборку System.Design.dll, необходимо изменить целевую рабочую среду проекта на .NET Framework 4.

    Public Class ColorLabelActionList
        Inherits System.ComponentModel.Design.DesignerActionList
    
    public class ColorLabelActionList :
              System.ComponentModel.Design.DesignerActionList
    
  2. В этот класс добавьте конструктор, который принимает экземпляр связанного элемента управления. Задайте частное поле для хранения ссылки на данный экземпляр. Задайте еще одно частное поле — для кэширования ссылки на DesignerActionService. Оно будет использоваться для обновления списка.

    Private colLabel As ColorLabel
    
    
    ...
    
    
    Private designerActionUISvc As DesignerActionUIService = Nothing
    
    
    ...
    
    
    Public Sub New(ByVal component As IComponent)
    
        MyBase.New(component)
        Me.colLabel = component
    
        ' Cache a reference to DesignerActionUIService, so the
        ' DesigneractionList can be refreshed.
        Me.designerActionUISvc = _
        CType(GetService(GetType(DesignerActionUIService)), _
        DesignerActionUIService)
    
    End Sub
    
    private ColorLabel colLabel;
    
    
    ...
    
    
    private DesignerActionUIService designerActionUISvc = null;
    
    
    ...
    
    
    public ColorLabelActionList( IComponent component ) : base(component) 
    {
        this.colLabel = component as ColorLabel;
    
        // Cache a reference to DesignerActionUIService, so the
        // DesigneractionList can be refreshed.
        this.designerActionUISvc =
            GetService(typeof(DesignerActionUIService))
            as DesignerActionUIService;
    }
    
  3. Добавьте методы и свойства, которые необходимо связать с элементами смарт-тегов. Методы выполняются, когда выбирается соответствующая им запись смарт-тега. Свойства должны иметь разделы средства получения значения для отображения их текущего значения, а если их значения свойств должны быть доступны для изменения из соответствующей записи смарт-тега, они могут иметь и разделы средства задания значения, использующие метод GetProperties.

    Примечание

    В среде разработки свойство может быть изменено только в том случае, если платформой .NET Framework предоставлен один из базовых типов, а этот тип может быть преобразован в базовый тип предоставленным TypeConverter, или когда предоставлен пользовательский UITypeEditor.

    Public Property ForeColor() As Color
        Get
            Return colLabel.ForeColor
        End Get
        Set(ByVal value As Color)
            GetPropertyByName("ForeColor").SetValue(colLabel, value)
        End Set
    End Property
    
    
    ...
    
    
    'Boolean properties are automatically displayed with binary 
    ' UI (such as a checkbox).
    Public Property LockColors() As Boolean
        Get
            Return colLabel.ColorLocked
        End Get
        Set(ByVal value As Boolean)
            GetPropertyByName("ColorLocked").SetValue(colLabel, value)
    
            ' Refresh the list.
            Me.designerActionUISvc.Refresh(Me.Component)
        End Set
    End Property
    
    
    ...
    
    
    Public Sub InvertColors()
        Dim currentBackColor As Color = colLabel.BackColor
        BackColor = Color.FromArgb( _
        255 - currentBackColor.R, _
        255 - currentBackColor.G, _
        255 - currentBackColor.B)
    
        Dim currentForeColor As Color = colLabel.ForeColor
        ForeColor = Color.FromArgb( _
        255 - currentForeColor.R, _
        255 - currentForeColor.G, _
        255 - currentForeColor.B)
    End Sub
    
    public Color ForeColor
    {
        get
        {
            return colLabel.ForeColor;
        }
        set
        {
            GetPropertyByName("ForeColor").SetValue(colLabel, value);
        }
    }
    
    
    ...
    
    
    // Boolean properties are automatically displayed with binary 
    // UI (such as a checkbox).
    public bool LockColors
    {
        get
        {
            return colLabel.ColorLocked;
        }
        set
        {
            GetPropertyByName("ColorLocked").SetValue(colLabel, value);
    
            // Refresh the list.
            this.designerActionUISvc.Refresh(this.Component);
        }
    }
    
    
    ...
    
    
    public void InvertColors()
    {
        Color currentBackColor = colLabel.BackColor;
        BackColor = Color.FromArgb(
            255 - currentBackColor.R, 
            255 - currentBackColor.G, 
            255 - currentBackColor.B);
    
        Color currentForeColor = colLabel.ForeColor;
        ForeColor = Color.FromArgb(
            255 - currentForeColor.R, 
            255 - currentForeColor.G, 
            255 - currentForeColor.B);
    }
    
  4. Можно также реализовать переопределенную версию метода GetSortedActionItems для возвращения массива экземпляров DesignerActionItem, где каждый элемент связан со свойством или методом, созданным на предыдущем этапе. Это можно сделать для изменения порядка элементов, их классификации или выборочного отображения. Список также может включать статические элементы, например заголовки логических групп.

    Public Overrides Function GetSortedActionItems() _
    As DesignerActionItemCollection
        Dim items As New DesignerActionItemCollection()
    
        'Define static section header entries.
        items.Add(New DesignerActionHeaderItem("Appearance"))
        items.Add(New DesignerActionHeaderItem("Information"))
    
        'Boolean property for locking color selections.
        items.Add(New DesignerActionPropertyItem( _
        "LockColors", _
        "Lock Colors", _
        "Appearance", _
        "Locks the color properties."))
    
        If Not LockColors Then
            items.Add( _
            New DesignerActionPropertyItem( _
            "BackColor", _
            "Back Color", _
            "Appearance", _
            "Selects the background color."))
    
            items.Add( _
            New DesignerActionPropertyItem( _
            "ForeColor", _
            "Fore Color", _
            "Appearance", _
            "Selects the foreground color."))
    
            'This next method item is also added to the context menu 
            ' (as a designer verb).
            items.Add( _
            New DesignerActionMethodItem( _
            Me, _
            "InvertColors", _
            "Invert Colors", _
            "Appearance", _
            "Inverts the fore and background colors.", _
            True))
        End If
        items.Add( _
        New DesignerActionPropertyItem( _
        "Text", _
        "Text String", _
        "Appearance", _
        "Sets the display text."))
    
        'Create entries for static Information section.
        Dim location As New StringBuilder("Location: ")
        location.Append(colLabel.Location)
        Dim size As New StringBuilder("Size: ")
        size.Append(colLabel.Size)
    
        items.Add( _
        New DesignerActionTextItem( _
        location.ToString(), _
        "Information"))
    
        items.Add( _
        New DesignerActionTextItem( _
        size.ToString(), _
        "Information"))
    
        Return items
    End Function
    
    public override DesignerActionItemCollection GetSortedActionItems()
    {
        DesignerActionItemCollection items = new DesignerActionItemCollection();
    
        //Define static section header entries.
        items.Add(new DesignerActionHeaderItem("Appearance"));
        items.Add(new DesignerActionHeaderItem("Information"));
    
        //Boolean property for locking color selections.
        items.Add(new DesignerActionPropertyItem("LockColors",
                         "Lock Colors", "Appearance",
                         "Locks the color properties."));
        if (!LockColors)
        {
            items.Add(new DesignerActionPropertyItem("BackColor",
                             "Back Color", "Appearance",
                             "Selects the background color."));
            items.Add(new DesignerActionPropertyItem("ForeColor",
                             "Fore Color", "Appearance",
                             "Selects the foreground color."));
    
            //This next method item is also added to the context menu 
            // (as a designer verb).
            items.Add(new DesignerActionMethodItem(this,
                             "InvertColors", "Invert Colors",
                             "Appearance",
                             "Inverts the fore and background colors.",
                              true));
        }
        items.Add(new DesignerActionPropertyItem("Text",
                         "Text String", "Appearance",
                         "Sets the display text."));
    
        //Create entries for static Information section.
        StringBuilder location = new StringBuilder("Location: ");
        location.Append(colLabel.Location);
        StringBuilder size = new StringBuilder("Size: ");
        size.Append(colLabel.Size);
        items.Add(new DesignerActionTextItem(location.ToString(),
                         "Information"));
        items.Add(new DesignerActionTextItem(size.ToString(),
                         "Information"));
    
        return items;
    }
    

Обновление связанного класса конструктора для реализации свойства ActionLists

  1. Найдите класс конструктора для элемента управления. Если такого класса не существует, создайте класс конструктора и свяжите его с классом элемента управления. Дополнительные сведения о конструкторах см. в разделе Базовые классы конструктора.

  2. В качестве способа оптимизации добавьте частное поле типа DesignerActionListCollection.

    Private lists As DesignerActionListCollection
    
    private DesignerActionListCollection actionLists;
    
  3. Добавьте переопределенное свойство ActionLists для возвращения нового экземпляра ранее созданного класса ColorLabelActionList.

    Public Overrides ReadOnly Property ActionLists() _
    As DesignerActionListCollection
        Get
            If lists Is Nothing Then
                lists = New DesignerActionListCollection()
                lists.Add( _
                New ColorLabelActionList(Me.Component))
            End If
            Return lists
        End Get
    End Property
    
    public override DesignerActionListCollection ActionLists
    {
        get
        {
            if (null == actionLists)
            {
                actionLists = new DesignerActionListCollection();
                actionLists.Add(
                    new ColorLabelActionList(this.Component));
            }
            return actionLists;
        }
    }
    

Комментарии

Несколько областей кода требуют более подробного объяснения:

  • Когда свойство или метод в классе, производном от DesignerActionList, изменяет состояние связанного элемента управления, для внесения этих изменений не должны использоваться вызовы свойств компонента, выполняемые непосредственно средством задания. Для этого необходимо использовать специально созданный PropertyDescriptor. Такой подход обеспечивает правильную работу функций отмены смарт-тега и обновления пользовательского интерфейса.

  • Можно выполнить динамическое обновление области смарт-тега с помощью вызова DesignerActionUIService.Refresh. Данный процесс используется для динамического изменения содержимого области смарт-тега. В примере смарт-теги, отвечающие за смену цветов, включаются условно в зависимости от состояния свойства LockColors. Данное логическое свойство также связано со смарт-тегом, поэтому разработчик может заблокировать или разблокировать выбранный цвет по меньшей мере через меню.

  • Запись смарт-тега типа DesignerActionMethodItem может при необходимости включаться в контекстное меню для связанного элемента управления с помощью установки для параметра includeAsDesignerVerb в конструкторе значения true. После этого платформа .NET Framework неявно создает соответствующую команду DesignerVerb и добавляет ее в контекстное меню. В данном примере это происходит с элементом InvertColors.

  • Элементы смарт-тегов группируются в области по свойству Category, которое задается в конструкторе для каждого элемента. Если это свойство не задано явно, оно назначается категории по умолчанию. Все элементы в области смарт-тега сортируются сначала по категории, а затем по порядку вхождения в массив DesignerActionItem, возвращаемый классом, производным от класса DesignerActionList. В этом примере содержатся две категории: Appearance и Information.

    Примечание

    Для второй категории DesignerActionHeaderItem не предоставляется.

  • Запись, отображающую сведения о статическом тексте, можно реализовать с помощью DesignerActionTextItem или DesignerActionPropertyItem, связанные свойства которых содержат только средство задания значения. В данном примере используется первый подход.

Следующие действия

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

См. также

Ссылки

DesignerVerb

DesignerActionItem

DesignerActionList

ActionLists

DesignerActionService

Основные понятия

Команды конструктора и объектная модель DesignerAction для Windows Forms