Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 891 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 36:

Интерфейс времени проектирования для компонента

Усовершенствование смарт-тега компонента

К созданному смарт-тегу можно сделать несколько замечаний

  1. По обновлению окна диалога:
    • при выполнении метода InvertColors успешно меняются цвета компонента, но цветовые поля самого смарт-тега не обновляются
  2. По оформлению окна диалога:
    • подписи элементов смарт-тега совпадают с именами свойств и методов, что не всегда может быть приемлемо для пользователя компонента. Было бы лучше написать их раздельно или вообще перевести на русский язык
    • порядком следования элементов в диалоговом окне смарт-тега формируется по алфавиту, а этим процессом желательно бы управлять

Устранение замечания по обновлению окна диалога

Для обновления диалогового окна смарт-тега при изменении цветов компонента нужно в конструкторе класса GradientLabelActionList формирования списка элементов сохранить ссылку на сервис System.ComponentModel.Design.DesignerActionUIService. Затем в нашем методе InvertColors() или в аксессорах set{ } свойств StartColor и EndColor вызвать метод Refresh() этого сервиса.

  • Дополните класс GradientLabelActionList компонента следующим кодом
//*///////////////////////////////////////////////////////////////
// Блок кода №3. Создание списка выносимых в смарт-тег элементов компонента
//////////////////////////////////////////////////////////////////
namespace MyControl
{
    // Пусть класс доступен коду только внутри сборки компонента
    internal partial class GradientLabelActionList : DesignerActionList
    {
        // Объявили ссылку на объект компонента
        GradientLabel gradientLabel;
    
        // Объявили ссылку на сервис смарт-тега
        DesignerActionUIService designerActionUIService;
    
        // Конструктор
        public GradientLabelActionList(IComponent component)
            : base(component)
        {
            // Привели и сохранили ссылку на редактируемый компонент
            gradientLabel = (GradientLabel)component;
    
            // Привели и сохранили ссылку на сервис смарт-тега
            designerActionUIService = (DesignerActionUIService)
                this.GetService(typeof(DesignerActionUIService));
        }
    
        // Вспомогательная функция реализации отражения
        private PropertyDescriptor GetPropertyByName(String propName)
        {
            PropertyDescriptor prop =
                TypeDescriptor.GetProperties(gradientLabel)[propName];
            if (prop == null)
                throw new ArgumentException("Свойство не существует", propName);
            return prop;
        }
    
        // Элементы компонента, выносимые в диалог смарт-тега
        public Color StartColor
        {
            get { return this.gradientLabel.StartColor; }
            set 
            { 
                this.GetPropertyByName("StartColor").SetValue(gradientLabel, value);
    
                // Обновляем диалоговое окно смарт-тега
                designerActionUIService.Refresh(gradientLabel);
            }
        }
        public Color EndColor
        {
            get { return this.gradientLabel.EndColor; }
            set 
            { 
                this.GetPropertyByName("EndColor").SetValue(gradientLabel, value);
    
                // Обновляем диалоговое окно смарт-тега
                designerActionUIService.Refresh(gradientLabel);
            }
        }
        public void InvertColors()
        {
            Color tmp = gradientLabel.StartColor;
            this.StartColor = gradientLabel.EndColor;
            this.EndColor = tmp;
        }
    }
}
//***************************************************************/
Листинг 36.11. Код класса GradientLabelActionList для обновления окна смарт-тега

Устранение замечания по оформлению окна диалога

Для того, чтобы изменить порядок следования элементов смарт-тега и сделать окно диалога более информативным, нужно изменить коллекцию элементов окна, представленную классом System.ComponentModel.Design.DesignerActionItemCollection. Для этого в классе формирования списка элементов окна GradientLabelActionList нужно переопределить унаследованный библиотечный метод DesignerActionList.GetSortedActionItems() и в нем вручную формировать коллекцию окна смарт-тега с нужным порядком элементов.

Каждый элемент коллекции окна смарт-тега представлен одним из классов:

  1. System.ComponentModel.Design.DesignerActionHeaderItem - устанавливает заголовок группы элементов окна смарт-тега
  2. System.ComponentModel.Design.DesignerActionTextItem - выводит надписи к элементам смарт-тега
  3. System.ComponentModel.Design.DesignerActionPropertyItem - представляет свойство и в зависимости от типа свойства виден как текстовое поле, выпадающий список или флажок
  4. System.ComponentModel.Design.DesignerActionMethodItem - представляет ссылку для вызова метода

Используем перечисленные классы представления элементов окна и сформируем коллекцию в переопределении виртуального метода GetSortedActionItems(). При этом создадим в смарт-теге три группы элементов:

  1. Группу свойств
  2. Группу методов
  3. Группу для отображения дополнительной информации
  • Добавьте в файл GradientLabelDesigner.cs блок кода №5, переопределяющий виртуальный метод DesignerActionList.GetSortedActionItems() базового класса
//*///////////////////////////////////////////////////////////////
// Блок кода №5. Ручное формирование списка элементов в классе GradientLabelActionList 
//////////////////////////////////////////////////////////////////
namespace MyControl
{
    partial class GradientLabelActionList
    {
        // Переопределяем виртуальный метод базового класса DesignerActionList
        public override DesignerActionItemCollection GetSortedActionItems()
        {
            // Создаем объект коллекции элементов смарт-тега
            DesignerActionItemCollection items = new DesignerActionItemCollection();
    
            // Формируем категорию "Свойства" (Properties)
            // Заголовок категории
            items.Add(new DesignerActionHeaderItem("Свойства", "Properties"));
            // Элементы категории 
            items.Add(new DesignerActionPropertyItem("StartColor", "Начальный цвет", 
                "Properties", "Цвет начала градиентной заливки"));
            items.Add(new DesignerActionPropertyItem("EndColor", "Конечный цвет",
                "Properties", "Цвет завершения градиентной заливки"));
    
            // Формируем категорию "Методы" (Methods), если цвета не равны!
            if (StartColor != EndColor)
            {
                // Заголовок категории 
                items.Add(new DesignerActionHeaderItem("Методы", "Methods"));
                // Ссылка вызова метода с одновременным созданием опции в контекстном меню
                items.Add(new DesignerActionMethodItem(this, "InvertColors",
                    "Перевернуть цвета", "Methods",
                    "Поменять начальный и конечный цвета местами", true));
            }
    
            // Формируем категорию "Информация" (Info)
            // Заголовок категории
            items.Add(new DesignerActionHeaderItem("Информация", "Info"));
            // Текстовый элемент категории 
            string info = String.Format("Размер компонента {0}x{1}",
                gradientLabel.Width, gradientLabel.Height);
            items.Add(new DesignerActionTextItem(info, "Info"));
    
            return items;
        }
    }
}
//***************************************************************/
Листинг 36.12. Дополнение в классе GradientLabelActionList кода формирования списка
  • Откомпилируйте проект компонента командой Build/Build Solution и убедитесь, что окно диалога компонента в режиме проектирования приобрело профессиональный вид