Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1447 / 158 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 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. Ввожу код на сайте, пишет:

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

 

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