Опубликован: 25.03.2010 | Уровень: для всех | Доступ: платный
Лекция 18:

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

Добавление в компонент пользовательского события расширенным способом

Рассмотрим другой способ работы с событиями, использующий базовое поле типа делегата. Для этого модифицируем наш компонент таким образом, чтобы будильник срабатывал два раза: по первому и второму событию. Но второе событие определим по иному.

  • Перейдите в режим редактирования компонента AlarmClock.cs [Design] и добавьте из панели Toolbox двойным щелчком кнопки мыши еще один системный таймер Timer
  • Выделите экземпляр таймера timer2 и в панели Properties установите свойство Interval=1000
  • Создайте для объекта timer2 обработчик события Tick с именем TimerHandlerExt, который переместите в отдельную часть класса AlarmClock в файле AlarmClock.cs. Заполните эту часть следующим кодом
// Часть 5
namespace MyCompany.MyComponents
{
    // Часть класса с определением обработчика события Tick 
    // системного таймера System.Windows.Forms.Timer timer2
    partial class AlarmClock
    {
    // Объявляем внутренние поля
    bool alarmFiredExt = false; // Состояние будильника (запущен/незапущен)
    DateTime alarmTimeExt = DateTime.Now; // Хранит время запуска будильника
    
    // Свойство для чтения и установки времени запуска будильника
    public DateTime AlarmTimeExt
        {
            get { return alarmTimeExt; }
            set
            {
                if (value != alarmTimeExt)
                {
                    alarmTimeExt = value;
                    alarmFiredExt = false;
                }
            }
        }
    
        // Свойство для проверки состояния хода второго
        // системного таймера, его остановки и запуска
        public bool EnabledExt
        {
            get { return timer2.Enabled; }
            set
            {
                timer2.Enabled = value;
                if (value)
                    alarmFiredExt = false;
            }
        }
        
    // Обработчик события срабатывания второго системного таймера
    private void TimerHandlerExt(object sender, EventArgs e)
    {
    DateTime now; // Текущее системное время
    AlarmEventArgs args;
    
    // В режиме разработки не выполнять
    if (!this.DesignMode)
      {
      now = DateTime.Now;
      // Если будильник не запущен и пришла пора запускать
      if (!alarmFiredExt && now >= alarmTimeExt)
        {
        // Создаем объект для передачи аргументов в событии
        args = new AlarmEventArgs();
        // Заполняем объект текущим временем
        args.Time = now;
        // Вызываем метод диспетчеризации события AlarmExt
        this.OnAlarmExt(args);
    
        // Поднимаем флаг "Будильник запущен"
        alarmFiredExt = true;
        }
      }
    }
    }
}
Листинг 18.17 . Часть класса с обработчиком таймера timer2 в файле AlarmClock.cs
  • Создайте часть класса компонента, объявляющего пользовательское событие на базе внутреннего поля-ссылки на экземпляр делегата, который будет содержать список зарегистрированных обработчиков этого события
// Часть 6 Extension
namespace MyCompany.MyComponents
{
    // Часть класса с определением собственного события
    // стандартным способом без использования базового поля
    partial class AlarmClock
    {
    // Закрытое поле-ссылка на экземпляр делегата
    // Для объявления поля решили использовать уже существующий 
    // делегат, но можно объявить и другой делегат с той же сигнатурой
    private AlarmHandler m_AlarmExt;
    
    // Объявляем пользовательское событие
    // с возможностью контроля доступа к нему
    public event AlarmHandler AlarmExt
    {
    // Эта функция будет вызвана при  попытке 
    // добавления обработчика в список вызова события
    add
    {
    // Здесь что-то можно проконтролировать, например, что
    // произошла попытка добавить обработчик в список вызова события
    Console.WriteLine("Добавлен обработчик в 
	список события AlarmExt");
    
    // Расширяем список объекта-делегата, ссылающегося на обработчики события
    m_AlarmExt += value;
    }
    // Эта функция будет вызвана при попытке 
    // изъятия обработчика из списка вызова события
    remove
    {
    // Здесь что-то можно проконтролировать, например, что
    // произошла попытка изъять обработчик из списка вызова события
    Console.WriteLine("Изъят обработчик из 
		списка события AlarmExt");
    
    // Удалим обработчик из списка объекта-делегата
    m_AlarmExt -= value;
    }
    }
    
        // Метод диспетчеризации события. Виртуальный и защищенный
        // для возможности переопределения в будущих потомках
        protected virtual void OnAlarmExt(AlarmEventArgs args)
        {
            // Проверяем наличие зарегистрированных обработчиков 
            // и генерируем событие через поле-делегат
            if (m_AlarmExt != null)
                m_AlarmExt(this, args);
        }
    }
}
Листинг 18.18 . Часть файла AlarmClock.cs объявления события с контролем списка делегата
  • Откомпилируйте библиотеку наших компонентов, выполнив команду Build/Build MyComponents
  • Перейдите в файл Form1.cs [Design] и добавьте в конструктор класса тестового приложения код настройки второго системного таймера экземпляра компонента alarmClock1
// Конструктор формы
        public Form1()
        {
            InitializeComponent();
    
            // Заполнение списка планетами
            for (int i = 0; i <= planets1.MaxIndex; i++)
            {
                listPlanets.Items.Add(String.Format(
                    "{0}) {1}", i, planets1[i]));
            }
    
            listPlanets.SelectedIndex = 0;
    
            // Устанавливаем время срабатывания будильника 
            // через 5 сек. после запуска системного таймера
            alarmClock1.AlarmTime = DateTime.Now.AddSeconds(5d);
            alarmClock1.Enabled = true;// Запускаем системный таймер
    
            // Настраиваем второй системный таймер компонента
            alarmClock1.AlarmTimeExt = DateTime.Now.AddSeconds(10d);
            alarmClock1.EnabledExt = true;// Запускаем системный таймер
        }
Листинг 18.19 . Конструктор формы Form1 файла Form1.cs приложения ComponentTest
  • На форме Form1 приложения ComponentTest выделите экземпляр alarmClock1 и через панель Properties в режиме Events создайте обработчик для события AlarmExt
  • Обработчик заполните следующим кодом
private void alarmClock1_AlarmExt(object sender, 
	AlarmClock.AlarmEventArgs e)
{
alarmClock1.EnabledExt = false;// Останавливаем второй системный таймер
    
int hour = alarmClock1.CurrentTime.Hour;
int minute = alarmClock1.CurrentTime.Minute;
int second = alarmClock1.CurrentTime.Second;
MessageBox.Show(String.Format("Сработал будильник!!!\n"
  + "Текущее время: {0} ч. {1} м. {2} с.", 
	hour, minute, second), "Доцент Снетков В.М.");
    
// Для генерации сообщения в консольный вывод
alarmClock1.AlarmExt -= alarmClock1_AlarmExt;
}
Листинг 18.20 . Обработчик события AlarmExt в тестирующем классе Form1
  • В панели Solution Explorer вызовите контекстное меню для узла приложения ComponentTest и выполните команду Properties
  • В появившемся окне настроек оболочки выберите вкладку Application и в раскрывающемся списке Output type включите окно консольного вывода Console Application

  • Запустите приложение и убедитесь, что оба способа определения пользовательского события работают одинаково, но в последнем способе мы можем контролировать процесс добавления обработчиков
Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.

 

Как активировать код?

Денис Пашков
Денис Пашков
Россия
Татьяна Ковалюк
Татьяна Ковалюк
Украина, Киев, Киевский политехнический институт, 1974