Пошаговое руководство. Создание составного элемента управления с помощью C#

Составные элементы управления предоставляют средства для создания и повторного использования настраиваемых графических интерфейсов. Составной элемент управления — это компонент, имеющий визуальное представление. Таким образом, он может состоять из одного или нескольких элементов управления, компонентов или блоков кода Windows Forms, позволяющих расширить функциональные возможности за счет проверки введенных пользователем данных, изменения свойств отображения или выполнения других предусмотренных разработчиком действий. Составные элементы управления можно вставлять в Windows Forms точно так же, как другие элементы управления. В первой части этого пошагового руководства мы создадим простой составной элемент управления с именем ctlClock. Во второй части мы расширим функциональность ctlClock за счет наследования.

Создание проекта

Создавая проект, вы указываете для него имя, чтобы задать корневое пространство имен, имя сборки и имя проекта, и необходимо убедиться в том, что компонент по умолчанию попадет в нужное пространство имен.

Создание библиотеки элементов управления ctlClockLib и элемента управления ctlClock

  1. В Visual Studio создайте новый проект библиотеки элементов управления Windows Forms и назначьте ему имя ctlClockLib.

    Имя проекта, ctlClockLib, по умолчанию также назначается корневому пространству имен. Корневое пространство имен используется для определения имен компонентов в сборке. Например, если в двух сборках содержатся компоненты с именем ctlClock, можно указать компонент ctlClock, используя ctlClockLib.ctlClock..

  2. В обозревателе решений щелкните файл UserControl1.cs правой клавишей мыши и выберите Переименовать. Измените имя файла на ctlClock.cs. Чтобы переименовать все ссылки на элемент кода UserControl1, в соответствующем запросе нажмите кнопку Да.

    Примечание.

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

  3. Сохраните проект, открыв меню Файл и выбрав пункт Сохранить все.

Добавление элементов управления и компонентов Windows в составной элемент управления

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

Добавление метки и таймера в составной элемент управления

  1. В обозревателе решений щелкните файл ctlClock.cs правой кнопкой мыши и выберите пункт Конструктор представлений.

  2. На панели элементов разверните узел Общие элементы управления, а затем дважды щелкните пункт Метка.

    Элемент управления Label с именем label1 добавляется в элемент управления на поверхности конструктора.

  3. В конструкторе щелкните пункт Label1. В окне свойств задайте следующие свойства.

    Свойство Изменить на
    Название lblDisplay
    Текст (blank space)
    TextAlign MiddleCenter
    Font.Size 14
  4. На панели элементов разверните узел Компоненты, а затем дважды щелкните пункт Таймер.

    Поскольку Timer является компонентом, он не имеет визуального представления в среде выполнения. В связи с этим он отображается не с элементами управления на поверхности конструктора, а в конструкторе компонентов (область в нижней части поверхности конструктора).

  5. В конструкторе компонентов щелкните timer1, а затем задайте для свойства Interval значение 1000 и для свойства Enabled значение true.

    Свойство Interval определяет частоту тактов компонента Timer. При каждом такте timer1 оно запускает код в событии timer1_Tick. Интервал представляет время между тактами в миллисекундах.

  6. В конструкторе компонентов дважды щелкните timer1, чтобы перейти к событию timer1_Tick для ctlClock.

  7. Измените код, как показано в следующем примере. Измените модификатор доступа с private на protected.

    protected void timer1_Tick(object sender, System.EventArgs e)
    {
        // Causes the label to display the current time.
        lblDisplay.Text = DateTime.Now.ToLongTimeString();
    }
    

    Этот код вызывает отображение текущего времени в lblDisplay. Поскольку для интервала timer1 было задано значение 1000, это событие возникает через каждую тысячу миллисекунд, а значит, текущее время обновляется каждую секунду.

  8. Измените метод, разрешив его переопределение с помощью ключевого слова virtual. Дополнительные сведения см. ниже в разделе "Наследование из пользовательского элемента управления".

    protected virtual void timer1_Tick(object sender, System.EventArgs e)
    
  9. Сохраните проект, открыв меню Файл и выбрав пункт Сохранить все.

Добавление свойств в составной элемент управления

Ваш элемент управления "Будильник" теперь включает элемент управления Label и компонент Timer, каждый из которых имеет собственный набор унаследованных свойств. Несмотря на то что отдельные свойства этих элементов управления не будут доступны последующим пользователям вашего элемента управления, вы можете создать и предоставить настраиваемые свойства, написав соответствующие блоки кода. Выполняя следующую процедуру, вы добавите в элемент управления свойства, позволяющие пользователю изменять цвет фона и текста.

Добавление свойства в составной элемент управления

  1. В обозревателе решений щелкните файл ctlClock.cs правой кнопкой мыши и выберите пункт Показать код.

    Откроется редактор кода для элемента управления.

  2. Найдите оператор public partial class ctlClock. Под открывающей скобкой ({) введите следующий код.

    private Color colFColor;
    private Color colBColor;
    

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

  3. Введите или вставьте следующий код под объявлениями переменных, созданными в шаге 2.

    // Declares the name and type of the property.
    public Color ClockBackColor
    {
        // Retrieves the value of the private variable colBColor.
        get
        {
            return colBColor;
        }
        // Stores the selected value in the private variable colBColor, and
        // updates the background color of the label control lblDisplay.
        set
        {
            colBColor = value;
            lblDisplay.BackColor = colBColor;
        }
    }
    // Provides a similar set of instructions for the foreground color.
    public Color ClockForeColor
    {
        get
        {
            return colFColor;
        }
        set
        {
            colFColor = value;
            lblDisplay.ForeColor = colFColor;
        }
    }
    

    Приведенный выше код обеспечивает доступ к двум настраиваемым свойствам, ClockForeColor и ClockBackColor, для последующих пользователей данного элемента управления. Операторы get и set позволяют хранить и извлекать значение свойства, а также предоставляют код для реализации соответствующих этому свойству функциональных возможностей.

  4. Сохраните проект, открыв меню Файл и выбрав пункт Сохранить все.

Тестирование элемента управления

Элементы управления не являются автономными приложениями и должны размещаться в контейнере. Проверьте поведение элемента управления в среде выполнения и испытайте его свойства в тестовом контейнере пользовательских элементов управления. Дополнительные сведения см. в разделе Практическое руководство. Тестирование поведения элемента UserControl во время выполнения.

Проверка элемента управления

  1. Нажмите клавишу F5, чтобы собрать проект и запустить элемент управления в тестовом контейнере элементов UserControl.

  2. В таблице свойств тестового контейнера выберите свойство ClockBackColor, а затем свойство, чтобы открыть палитру цветов.

  3. Щелкните нужный цвет.

    Цвет фона элемента управления изменится на выбранный.

  4. Используя аналогичную последовательность событий, проверьте, функционирует ли свойство ClockForeColor должным образом.

    Из этого и предыдущих разделов вы узнали, как объединить компоненты и элементы управления Windows с кодом и упаковкой и, таким образом, предоставить настраиваемые функциональные возможности в виде составного элемента управления. Вы узнали, как вывести свойства в составной элемент управления и проверить элемент управления после того, как он будет готов. В следующем разделе вы узнаете, как сконструировать производный составной элемент управления, используя в качестве базы ctlClock.

Наследование из составного элемента управления

В предыдущих разделах вы узнали, как объединить элементы управления, компоненты и код Windows в составные элементы управления, доступные для повторного использования. После этого составной элемент управления можно использовать как базу, на основе которой будут создаваться другие элементы управления. Процесс создания класса, производного от базового, называется наследованием. В этом разделе вы создадите составной элемент управления с именем ctlAlarmClock. Он будет производным от родительского элемента управления, ctlClock. Вы узнаете, как расширить функциональные возможности ctlClock, переопределив методы родительского класса и добавив новые методы и свойства.

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

Создание производного элемента управления

  1. В обозревателе решений щелкните правой кнопкой мыши ctlClockLib, выберите пункт Добавить, а затем выберите Пользовательский элемент управления.

    Откроется диалоговое окно Добавление нового элемента .

  2. Выберите шаблон Производный пользовательский элемент управления.

  3. В поле Имя введите ctlAlarmClock.cs и нажмите кнопку Добавить.

    Откроется диалоговое окно Выбор компонентов для наследования.

  4. В разделе Имя компонента дважды щелкните файл ctlClock.

  5. В обозревателе решений просмотрите список текущих проектов.

    Примечание.

    Файл с именем элемент ctlAlarmClock. cs будет добавлен в текущий проект.

Добавление свойств будильника

Свойства, добавляются в производный элемент управления точно так же, как в составной элемент управления. Теперь, используя синтаксис объявления свойств, добавим в элемент управления два свойства: свойство AlarmTime, в котором хранится значение даты и времени отключения будильника, и свойство AlarmSet, определяющее время срабатывания будильника.

Добавление свойств в составной элемент управления

  1. В обозревателе решений щелкните файл ctlAlarmClock правой кнопкой мыши и выберите пункт Показать код.

  2. Найдите оператор public class. Обратите внимание, что элемент управления наследуется из ctlClockLib.ctlClock. Под открывающей скобкой оператора ({) введите следующий код.

    private DateTime dteAlarmTime;
    private bool blnAlarmSet;
    // These properties will be declared as public to allow future
    // developers to access them.
    public DateTime AlarmTime
    {
        get
        {
            return dteAlarmTime;
        }
        set
        {
            dteAlarmTime = value;
        }
    }
    public bool AlarmSet
    {
        get
        {
            return blnAlarmSet;
        }
        set
        {
            blnAlarmSet = value;
        }
    }
    

Добавление графического интерфейса элемента управления

Производный элемент управления получает такой же графический интерфейс, как у того элемента, из которого он наследуется. Кроме того, он включает те же составные элементы управления, что и родительский элемент управления, однако свойства этих составных элементов будут доступны, только если предоставить их напрямую. Графический интерфейс производного элемента управления добавляется точно так же, как и для любого составного элемента управления. Чтобы продолжить добавление графического интерфейса для будильника, добавим элемент управления Label, который будет мигать при срабатывании будильника.

Добавление элемента управления Label

  1. В обозревателе решений щелкните файл ctlAlarmClock правой кнопкой мыши и выберите пункт Конструктор представлений.

    Конструктор для ctlAlarmClock откроется в главном окне.

  2. Нажмите на отображаемую область элемента управления и просмотрите окно свойств.

    Примечание.

    Все свойства отображаются, но недоступны. Это означает, что эти свойства являются собственными свойствами lblDisplay, в окне свойств изменить их или получить к ним доступ нельзя. По умолчанию элементы управления, входящие в составной элемент управления, имеют статус private и их свойства недоступны.

    Примечание.

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

  3. Добавьте элемент управления Label в составной элемент управления.

  4. С помощью мыши перетащите элемент управления Label непосредственно под окно отображения. В окне свойств задайте следующие свойства.

    Свойство Параметр
    Название lblAlarm
    Текст Alarm!
    TextAlign MiddleCenter
    Visible false

Добавление функциональных возможностей будильника

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

Переопределение метода Timer1_Tick в ctlClock

  1. В редакторе кода найдите оператор private bool blnAlarmSet;. Сразу после него добавьте следующий оператор.

    private bool blnColorTicker;
    
  2. В редакторе кода найдите закрывающую скобку (}) в конце класса. Непосредственно перед скобкой добавьте следующий код.

    protected override void timer1_Tick(object sender, System.EventArgs e)
    {
        // Calls the Timer1_Tick method of ctlClock.
        base.timer1_Tick(sender, e);
        // Checks to see if the alarm is set.
        if (AlarmSet == false)
            return;
        else
            // If the date, hour, and minute of the alarm time are the same as
            // the current time, flash an alarm.
        {
            if (AlarmTime.Date == DateTime.Now.Date && AlarmTime.Hour ==
                DateTime.Now.Hour && AlarmTime.Minute == DateTime.Now.Minute)
            {
                // Sets lblAlarmVisible to true, and changes the background color based on
                // the value of blnColorTicker. The background color of the label
                // will flash once per tick of the clock.
                lblAlarm.Visible = true;
                if (blnColorTicker == false)
                {
                    lblAlarm.BackColor = Color.Red;
                    blnColorTicker = true;
                }
                else
                {
                    lblAlarm.BackColor = Color.Blue;
                    blnColorTicker = false;
                }
            }
            else
            {
                // Once the alarm has sounded for a minute, the label is made
                // invisible again.
                lblAlarm.Visible = false;
            }
        }
    }
    

    Добавление этого кода решает сразу несколько задач. Оператор override указывает элементу управления использовать этот метод вместо метода, унаследованного из базового элемента управления. При вызове этого метода он вызывает переопределяемый метод, используя оператор base.timer1_Tick, и следит за тем, чтобы в этом элементе управления были реализованы все функции исходного элемента управления. Затем он выполняет дополнительный код, реализующий функции будильника. Когда будильник срабатывает, появляется мигающая метка.

    Элемент управления "Будильник" почти готов. Осталось реализовать только его отключение. Для этого нужно добавить код в метод lblAlarm_Click.

Реализация метода отключения

  1. В обозревателе решений щелкните файл ctlAlarmClock.cs правой кнопкой мыши и выберите пункт Конструктор представлений.

    Откроется конструктор.

  2. Добавьте кнопку в элемент управления. Задайте свойства для этой кнопки следующим образом.

    Свойство Значение
    Название btnAlarmOff
    Текст Отключить оповещение
  3. В конструкторе дважды щелкните элемент управления btnAlarmOff.

    Откроется редактор кода со строкой private void btnAlarmOff_Click.

  4. Измените метод, как показано в следующем коде.

    private void btnAlarmOff_Click(object sender, System.EventArgs e)
    {
        // Turns off the alarm.
        AlarmSet = false;
        // Hides the flashing label.
        lblAlarm.Visible = false;
    }
    
  5. Сохраните проект, открыв меню Файл и выбрав пункт Сохранить все.

Использование унаследованного элемента управления в форме

Унаследованный элемент управления проверяется точно так же, как элемент управления базового класса ctlClock: нажмите клавишу F5, чтобы выполнить сборку проекта и запустить элемент управления в тестовом контейнере UserControl. Дополнительные сведения см. в разделе Практическое руководство. Тестирование поведения элемента UserControl во время выполнения.

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

Сборка и добавление элемента управления в тестовую форму

  1. В обозревателе решений щелкните ctlClockLib правой кнопкой мыши и выберите пункт Сборка.

  2. Добавьте в решение новый проект приложения Windows Forms с именем Test.

  3. В обозревателе решений щелкните узел Ссылки для своего нового тестового проекта. Щелкните Добавить ссылку, чтобы открыть диалоговое окно Добавление ссылки. Выберите вкладку Проекты. Проект ctlClockLib будет указан под полем Имя проекта. Дважды щелкните проект, чтобы добавить ссылку на тестовый проект.

  4. В обозревателе решений щелкните Test правой кнопкой мыши и выберите пункт Сборка.

  5. На панели элементов разверните узел Компоненты ctlClockLib.

  6. Дважды щелкните ctlAlarmClock, чтобы добавить копию ctlAlarmClock в свою форму.

  7. В панели элементов найдите и дважды щелкните DateTimePicker, чтобы добавить элемент управления DateTimePicker в форму, а затем добавьте элемент управления Label, дважды щелкнув пункт Метка.

  8. С помощью мыши разместите элементы управления в удобном месте формы.

  9. Задайте свойства этих элементов управления следующим образом.

    Элемент управления Свойство значение
    label1 Текст (blank space)
    Название lblTest
    dateTimePicker1 Название dtpTest
    Формат Time
  10. В конструкторе дважды щелкните dtpTest.

    В редакторе кода откроется private void dtpTest_ValueChanged.

  11. Измените код, как показано в следующем примере.

    private void dtpTest_ValueChanged(object sender, System.EventArgs e)
    {
        ctlAlarmClock1.AlarmTime = dtpTest.Value;
        ctlAlarmClock1.AlarmSet = true;
        lblTest.Text = "Alarm Time is " +
            ctlAlarmClock1.AlarmTime.ToShortTimeString();
    }
    
  12. В обозревателе решений щелкните правой кнопкой мыши Test и выберите пункт Назначить запускаемым проектом.

  13. В меню Отладка выберите пункт Начать отладку.

    Запустится тестовая программа. Обратите внимание, что текущее время обновляется в элементе управления ctlAlarmClock, а время начала показывается в элементе управления DateTimePicker.

  14. Щелкните DateTimePicker, где отображаются минуты часа.

  15. С помощью клавиатуры укажите значение минут, составляющее на одну минуту больше текущего времени, отображаемого ctlAlarmClock.

    Время включения будильника отображается в lblTest. Дождитесь момента, когда отображаемое время совпадет с установленным временем будильника. Когда это произойдет, lblAlarm начнет мигать.

  16. Отключите сигнал, нажав btnAlarmOff. Теперь будильник можно сбросить.

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

См. также