Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 24:

Пользовательские компоненты

Аннотация: Рассматриваются этапы разработки компонентов. Выбор базового класса компонента. Создание визуального компонента FirstComponent. Пробное тестирование компонента. Развертывание свойств вложенного объекта компонента. Установка значений свойств компонента по умолчанию. Создание невизуального компонента Planets. Создание невизуального компонента-будильника AlarmClock (тревожные часы) с собственным событием. Добавление в компонент пользовательского события стандартным способом. Тестирование компонента AlarmClock. Добавление в компонент пользовательского события расширенным способом.
Ключевые слова: компонент, единица, класс, абстракция, Пользовательские компоненты, испытание, документирование, инструментальные панели, базовый тип, component, расширение класса, custom control, список, IDE, UserControl, композиция, очередь, пространство, namespace, оболочка, Object Browser, browsing, представление, время выполнения, перечисление, базовый класс, init, ссылка, цвет фона, вызов метода, конструктор класса, этапы проектирования, объект, свойство класса, startup, режим конструктора, исполняемый файл, значимый тип, ссылочный тип, сложный тип, поле, полное имя, тип объекта, развертывание, атрибут, system, методы класса, виртуальный метод, converter, перегруженный метод, конструктор, region, информация, пользователь, доступ, индексатор, массив, rebuild, BorderStyle, sans serif, bold, ReadOnly, event, keypresses, сигнатура, код программы, адресация, dispatching, method, операции, таймер, Timer, системный таймер, interval, tick, файл, пользовательское событие, делегаты, alarm, экземпляры делегата

Файлы к лабораторной работе Вы можете скачать здесь.

Основными вида создания программного продукта являются:

  1. Создание приложений
  2. Создание библиотек классов
  3. Создание компонентов

В данном разделе мы познакомимся с созданием компонентов. Компонент, это программная единица, способная поддерживать технологию визуального программирования. Это не только класс, обладающий нужной функциональностью на этапе выполнения, но и абстракция, поддерживаемая инструментами оболочки на этапе проектирования. В отличие от стандартных библиотечных компонентов, созданных разработчиками среды проектирования, их называют пользовательскими. Пользовательский компонент можно перетаскивать из панели Toolbox на форму, настраивать его свойства и события точно также, как это делается со стандартными компонентами библиотеки .NET Framework.

Этапы разработки компонентов

Стандартная процедура создания пользовательского компонента состоит из следующих шагов:

  1. Выбор базового класса
  2. Создание структуры нового класса
  3. Добавление свойств, методов, событий
  4. Испытание компонента
  5. Документирование пользовательского компонента
  6. Сохранение компонента в DLL
  7. Добавление компонента в инструментальную панель среды проектирования

Далее мы опробуем большинство из этих этапов на примере создания трех пользовательских компонентов.

Выбор базового класса компонента

В зависимости от выбора базового типа различают следующие компоненты

  • Пользовательские элементы управления (user control) - расширение визуальных элементов управления, в основе которых лежит класс Control
  • Невизуальные компоненты (nonvisual component) - расширения классов, не имеющих во время выполнения визуального представления
  • Специальные элементы управления (custom control) - создание совершенно нового визуального компонента непосредственно из класса Control

Ниже приведен список базовых классов среды .NET Framework, используемых при создании компонентов

Базовые классы компонентов
Класс .NET Framework Описание
Object Для создания компонента с нуля
System.ComponentModel.Component Для наследования функциональности времени разработки в среде IDE
System.Windows.Forms.Control Для разработки визуальных компонентов
System.Windows.Forms.UserControl Работает подобно форме в IDE для композиции нескольких элементов управления. Используется при создании сложных визуальных компонентов, состоящих из нескольких других компонентов
Любой библиотечный компонент Можно расширять любой библиотечный компонент путем наследования

Упражнение 1. Создание визуального компонента FirstComponent

Создадим компонент под названием FirstComponent, который будет потомком класса System.Windows.Forms.Control сборки System.Windows.Forms. В свою очередь, этот библиотечный класс Control наследует от класса System.ComponentModel.Component сборки System. Нам понадобятся следующие пространства имен:

Пространства имен и сборки
Пространство имен Библиотечная сборка
System.Windows.Forms System.Windows.Forms.dll
System.ComponentModel System.dll
System.Drawing System.Drawing.dll
System mscorlib.dll
System.Collections mscorlib.dll
  • Выполните команду File/New/Project оболочки Visual Studio 2005 и заполните окно мастера так

Мастер создаст каталог решения MySolution для размещения нескольких взаимосвязанных проектов, в который поместит каталог проекта MyComponents и будет автоматически обертывать каждый новый класс проекта при его создании пространством имен MyComponents.

Для тренировки нам нужно настроить оболочку на автоматическое генерирование другого пространства имен для всех файлов проекта, которое бы уникально характеризовало нашу библиотеку компонентов. Для будующих компонентов мы выберем составное пространство имен MyCompany.MyComponents.

  • В панели Solution Explorer вызовите контекстное меню для корневого узла проекта MyComponents и выполните команду Properties. Для вкладки Application скорректируйте текстовое поле Default namespace как показано на рисунке

  • Удалите автоматически созданный оболочкой файл Class1.cs
  • В панели Solution Explorer выделите корневой узел проекта, выполните команду Project/Add Component и задайте имя файла FirstComponent.cs

  • В конструкторе файла щелкните на соответствующей ссылке или выполните команду контекстного меню, чтобы перейти в режим редактирования кода


Код заготовки компонента, созданный мастером, будет выглядеть так

using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
    
namespace MyCompany.MyComponents
{
    public partial class FirstComponent : Component
    {
        public FirstComponent()
        {
            InitializeComponent();
        }
    
        public FirstComponent(IContainer container)
        {
            container.Add(this);
    
            InitializeComponent();
        }
    }
}
Листинг 24.1. Код заготовки компонента FirstComponent

Обратите внимание, что класс объявлен как partial (частичный), что позволит для удобства чтения разбить его описание на отдельные части, или даже разместить эти описания в отдельных файлах. Удостоверьтесь, что теперь оболочка автоматически генерирует установленное нами составное пространство имен MyCompany.MyComponents.

  • Выполните команду Project/Add Reference, перейдите на вкладку .NET и, удерживая клавишу Ctrl, добавьте к проекту ссылки на библиотечные сборки (сборка mscorlib.dll подключается автоматически):
    • System.dll
    • System.Windows.Forms.dll
    • System.Drawing.dll
  • Раскройте в панели Solution Explorer узел References и удалите из проекта ссылки на ненужные сборки, автоматически сгенерированные мастером оболочки


  • Откройте панель Object Browser, установите раскрывающийся список Browse в значение .NET Framework, раскройте сборку System.Windows.Forms, в которой найдите класс System.Windows.Forms.Control. Убедитесь, что класс Control является потомком класса System.ComponentModel.Component


Это значит, что в своем коде мы можем наследовать класс FirstComponent не от базового класса Component, как это предполагал мастер создания заготовки компонента, а от визуального класса Control. В результате компонент FirstComponent будет иметь визуальное представление на форме как во время проектирования, так и во время выполнения.

  • Заполните файл FirstComponent.cs следующим кодом
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections;
    
namespace MyCompany.MyComponents
{
    public partial class FirstComponent : Control
    {
        public FirstComponent()
        {
            InitializeComponent();
            Init();
        }
    
        public FirstComponent(IContainer container)
        {
            container.Add(this);
            InitializeComponent();
            Init();
        }
    }
}
    
namespace MyCompany.MyComponents
{
    // Определяем перечисление
    public enum EnumType { Zero, One, Two, Three };
    
    partial class FirstComponent
    {
        // Локальные поля
        int integerProp;
        string stringProp = "По умолчанию";
        char charProp;
        bool boolProp = false;
        EnumType enumProp = EnumType.Zero;
        SomeObject someObject;
      
        // Общедоступные свойства для локальных полей
        public int IntegerProp
        {
            get { return integerProp; }
            set { integerProp = value; }
        }
    
        public string StringProp
        {
            get { return stringProp; }
            set { stringProp = value; }
        }
    
        public char CharProp
        {
            get { return charProp; }
            set { charProp = value; }
        }
    
        public bool BoolProp
        {
            get { return boolProp; }
            set { boolProp = value; }
        }
    
        public EnumType EnumProp
        {
            get { return enumProp; }
            set { enumProp = value; }
        }
    
        // Сложное свойство - объект  
        public SomeObject SomeObj
        {
            get { return someObject; }
            set { someObject = value; }
        }
    
        void Init()
        {
            someObject = new SomeObject();
            this.BackColor = System.Drawing.Color.Red;
        }
    }
}
    
namespace MyCompany.MyComponents
{
    public class SomeObject : Object
    {
        int prop1;
        string prop2;
    
        // Свойства
        public int Prop1
        {
            get { return prop1; }
            set { prop1 = value; }
        }
    
        public string Prop2
        {
            get { return prop2; }
            set { prop2 = value; }
        }
    
        // Инициализация полей через конструктор
        public SomeObject()
        {
            prop1 = 2008;
            prop2 = "Привет";
        }
    }
}
Листинг 24.2. Модифицированный код файла FirstComponent.cs

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

Мы поменяли базовый класс Component на Control для того, чтобы сделать компонент визуальным. Базовые поля для свойств класса SomeObject мы инициализировали в конструкторе по умолчанию (для разнообразия). В методе Init() мы создали экземпляр класса SomeObject и инициализировали им внутреннюю ссылку, чтобы при создании самого компонента ссылка бы адресовалась к уже существующему объекту. Мы, также, установили цвет фона компонента для его видимости на вызывающей форме.

Вызов метода Init() поместили внутрь перегруженных версий конструктора класса компонента последним. Конструкторы компонента выполняются оболочкой и на этапе проектирования. Для контролируемого доступа к ссылке на объект извне предусмотрели внутри класса компонента общедоступное свойство. Класс компонента мы разбили на отдельные части, упаковав их в одно и то же пространство имен.

Иван Циферблат
Иван Циферблат
Россия, Таганрог, 36, 2000