Поделиться через


Прием событий

Для приема события в приложении необходимо предоставить обработчик событий (метод обработки событий), который выполняет логику программы в ответ на событие и регистрирует обработчик событий с источником событий. Этот процесс также называют привязкой событий. Визуальные конструкторы для форм Windows Forms и веб-форм предоставляют средства быстрой разработки приложений (RAD — Rapid Application Development), которые упрощают или скрывают подробности привязки событий.

В этом разделе описывается общий шаблон обработки событий. Общие сведения о модели событий в платформе .NET Framework см. в разделе События и делегаты. Дополнительные сведения о модели событий Windows Forms см. в разделе Практическое руководство. Прием событий в приложениях Windows Forms. Дополнительные сведения о модели событий веб-форм см. в разделе Практическое руководство. Прием событий в приложениях Web Forms.

Шаблон событий

Подробности привязки событий для форм Windows Forms и веб-форм отличаются из-за разных уровней поддержки разными средствами RAD. Однако в обоих сценариях используется один и тот же шаблон событий, обладающий следующими характеристиками:

  • Класс, вызывающий событие с именем EventName, имеет следующий элемент:
Public Event EventName As EventNameEventHandler
public event EventNameEventHandler EventName;
public:
    event EventNameEventHandler^ EventName;
  • Делегатом события для события EventName является EventNameEventHandler со следующей сигнатурой:
Public Delegate Sub EventNameEventHandler(sender As Object, e As EventNameEventArgs)
public delegate void EventNameEventHandler(object sender, EventNameEventArgs e);
delegate void EventNameEventHandler(Object^ sender, EventNameEventArgs^ e);

Для приема события EventName обработчик событий должен иметь такую же сигнатуру, что и делегат события.

Sub EventHandler(sender As Object, e As EventNameEventArgs)
End Sub
void EventHandler(object sender, EventNameEventArgs e) {}
void EventHandler(Object^ sender, EventNameEventArgs^ e) {}

Примечание

Делегат событий в платформе .NET Framework называется EventNameEventHandler, тогда как в документации под термином "обработчик событий" понимается метод обработки событий.Смысл в выборе такого названия заключается в том, что делегат EventNameEventHandler указывает на обработчик событий (метод), который, собственно, и обрабатывает событие.

Если событие не имеет связанных данных, то класс, создающий событие, использует System.EventHandler в качестве делегата и System.EventArgs в качестве данных события. События, которые имеют связанные данные, используют классы, производные от классов EventArgs, которые в свою очередь извлекаются из типа данных события и используют соответствующий тип делегата событий. Например, если требуется обработать событие MouseUp в приложении Windows Forms, то классом данных события будет являться MouseEventArgs, а делегатом события — MouseEventHandler. Обратите внимание, что несколько событий мыши используют общий класс для данных события и общего делегата события, поэтому схема назначения имен не точно соответствует схеме, описанной выше. Для обработки событий мыши обработчик событий должен иметь следующую сигнатуру:

Sub Mouse_Moved(sender As Object, e As MouseEventArgs)
End Sub
void Mouse_Moved(object sender, MouseEventArgs e){}
void Mouse_Moved(Object^ sender, MouseEventArgs^ e){}

Параметры, задающие отправителя и аргументы события, предоставляют обработчику дополнительные сведения о событии, пришедшем от мыши. Объект sender указывает на объект, создавший событие. Параметр MouseEventArgs предоставляет сведения о перемещении мыши, вызвавшем событие. Многие источники событий предоставляют дополнительные данные о событии, которые многие обработчики событий используют в процессе обработки. Пример, демонстрирующий создание и обработку событий с дополнительными данными, содержится в разделе Практическое руководство. Создание и прием событий.

Примечание

События также возникают вне контекста пользовательского интерфейса (UI); платформа .NET Framework включает в себя множество классов, не принадлежащих пользовательскому интерфейсу, которые вызывают события.Тем не менее все события подходят под описанный здесь шаблон.

Сведения о вызове событий из класса см. в разделе Создание события.

Статические и динамические события

.NET Framework позволяет подписчикам регистрироваться для получения уведомлений о событиях как статически, так и динамически. Статические обработчики событий действуют на протяжении всего срока существования класса, события которого они обрабатывают. Это наиболее распространенный способ обработки событий. Динамические обработчики событий явным образом активируются и деактивируются во время выполнения программы. Обычно это происходит при выполнении каких-либо условий, определяемых логикой программы. Например, их можно использовать в случаях, когда уведомление о событиях требуются только в определенных случаях или когда в приложении используется несколько обработчиков событий и нужный из них определяется во время выполнения программы.

Метод EventInfo.AddEventHandler добавляет динамические обработчики событий, а метод EventInfo.RemoveEventHandler деактивирует их. В различных языках имеются собственные возможности для динамической обработки событий. В следующем примере определяется класс TemperatureMonitor, который создает событие TemperatureTheshold всякий раз, когда температура достигает заранее установленного порогового значения. Обработчик этого события активируется и деактивируется в процессе выполнения программы.

public class TemperatureEventArgs : Inherits EventArgs
   Private oldTemp As Decimal
   Private newTemp As Decimal

   Public ReadOnly Property OldTemperature As Decimal
      Get
         Return Me.oldTemp
      End Get   
   End Property

   Public ReadOnly Property NewTemperature As Decimal
      Get
         Return Me.newTemp
      End Get
   End Property

   Public Sub New(oldTemp As Decimal, newTemp As Decimal)
      Me.oldTemp = oldTemp
      Me.newTemp = newTemp   
   End Sub
End Class

Public Delegate Sub TemperatureEventHandler(sender As Object, _
                                            ev As TemperatureEventArgs)

Public Class TemperatureMonitor
   Private currentTemperature As Decimal
   Private threshholdTemperature As Decimal

   Public Event TemperatureThreshold As TemperatureEventHandler 

   Public Sub New(threshHold As Decimal)
      Me.threshholdTemperature = threshHold
   End Sub

   Public Sub SetTemperature(newTemperature As Decimal)
      If (Me.currentTemperature > threshholdTemperature And _
         newTemperature <= Me.threshholdTemperature) Or _
         (Me.CurrentTemperature < Me.threshholdTemperature And _
             newTemperature >= Me.threshholdTemperature) Then
         OnRaiseTemperatureEvent(newTemperature)
      End If
      Me.currentTemperature = newTemperature
   End Sub

   Public Function GetTemperature() As Decimal
      Return Me.currentTemperature
   End Function

   Protected Overridable Sub OnRaiseTemperatureEvent(newTemperature As Decimal)
      RaiseEvent TemperatureThreshold(Me, New TemperatureEventArgs(Me.currentTemperature, _ 
                                       newTemperature))
   End Sub                                       
End Class

Public Module Example
   Public Sub Main()
      Dim tempMon As New TemperatureMonitor(32d)
      tempMon.SetTemperature(33)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
                        tempMon.GetTemperature())
      tempMon.SetTemperature(32)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
                        tempMon.GetTemperature())

      ' Add event handler dynamically using Visual Basic syntax.
      AddHandler tempMon.TemperatureThreshold, AddressOf TempMonitor

      tempMon.SetTemperature(33)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
                        tempMon.GetTemperature())
      tempMon.SetTemperature(34)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
                        tempMon.GetTemperature())
      tempMon.SetTemperature(32)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _
                        tempMon.GetTemperature())

      ' Remove event handler dynamically using Visual Basic syntax.
      RemoveHandler tempMon.TemperatureThreshold, AddressOf TempMonitor

      tempMon.SetTemperature(31)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _ 
                        tempMon.GetTemperature())
      tempMon.SetTemperature(35)
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", _ 
                        tempMon.GetTemperature())
   End Sub

   Private Sub TempMonitor(sender As Object, e As TemperatureEventArgs)
      Console.WriteLine("   ***Warning: Temperature is changing from {0} to {1}.", _ 
                        e.OldTemperature, e.NewTemperature)
   End Sub 
End Module
' The example displays the following output:
'       Current temperature is 33 degrees Fahrenheit.
'       Current temperature is 32 degrees Fahrenheit.
'       Current temperature is 33 degrees Fahrenheit.
'       Current temperature is 34 degrees Fahrenheit.
'          ***Warning: Temperature is changing from 34 to 32.
'       Current temperature is 32 degrees Fahrenheit.
'       Current temperature is 31 degrees Fahrenheit.
'       Current temperature is 35 degrees Fahrenheit.
using System;

public class TemperatureEventArgs : EventArgs
{
   private decimal oldTemp;
   private decimal newTemp;

   public decimal OldTemperature
   {
      get { return this.oldTemp; }
   }

   public decimal NewTemperature
   {
      get { return this.newTemp; }
   }

   public TemperatureEventArgs(decimal oldTemp, decimal newTemp)
   {
      this.oldTemp = oldTemp;
      this.newTemp = newTemp;   
   }
}

public delegate void TemperatureEventHandler(object sender, TemperatureEventArgs ev);

public class TemperatureMonitor
{
   private decimal currentTemperature;
   private decimal threshholdTemperature;

   public event TemperatureEventHandler TemperatureThreshold; 

   public TemperatureMonitor(decimal threshhold)
   {
      this.threshholdTemperature = threshhold;
   }

   public void SetTemperature(decimal newTemperature)
   {
      if ( (this.currentTemperature > this.threshholdTemperature && 
           newTemperature <= this.threshholdTemperature) ||
           (this.currentTemperature < this.threshholdTemperature &&
           newTemperature >= this.threshholdTemperature) )
         OnRaiseTemperatureEvent(newTemperature);
      this.currentTemperature = newTemperature;
   }

   public decimal GetTemperature()
   {
      return this.currentTemperature;
   }

   protected virtual void OnRaiseTemperatureEvent(decimal newTemperature)
   {
      // Raise the event if it has subscribers.
      if (TemperatureThreshold != null)
         TemperatureThreshold(this, new TemperatureEventArgs(this.currentTemperature, 
                               newTemperature));
   }
}

public class Example
{
   public static void Main()
   {
      Example ex = new Example();
      ex.MonitorTemperatures();
   }

   public void MonitorTemperatures()
   {
      TemperatureMonitor tempMon = new TemperatureMonitor(32);
      tempMon.SetTemperature(33);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", 
                        tempMon.GetTemperature());
      tempMon.SetTemperature(32);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
                        tempMon.GetTemperature());

      // Add event handler dynamically using C# syntax.
      tempMon.TemperatureThreshold += this.TempMonitor;

      tempMon.SetTemperature(33);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", 
                        tempMon.GetTemperature());
      tempMon.SetTemperature(34);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", 
                        tempMon.GetTemperature());
      tempMon.SetTemperature(32);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.",
                        tempMon.GetTemperature());

      // Remove event handler dynamically using C# syntax.
      tempMon.TemperatureThreshold -= this.TempMonitor;

      tempMon.SetTemperature(31);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", 
                        tempMon.GetTemperature());
      tempMon.SetTemperature(35);
      Console.WriteLine("Current temperature is {0} degrees Fahrenheit.", 
                        tempMon.GetTemperature());
   }

   private void TempMonitor(object sender, TemperatureEventArgs e)
   {
      Console.WriteLine("   ***Warning: Temperature is changing from {0} to {1}.", 
                        e.OldTemperature, e.NewTemperature);
   } 
}
// The example displays the following output:
//       Current temperature is 33 degrees Fahrenheit.
//       Current temperature is 32 degrees Fahrenheit.
//       Current temperature is 33 degrees Fahrenheit.
//       Current temperature is 34 degrees Fahrenheit.
//          ***Warning: Temperature is changing from 34 to 32.
//       Current temperature is 32 degrees Fahrenheit.
//       Current temperature is 31 degrees Fahrenheit.
//       Current temperature is 35 degrees Fahrenheit.

См. также

Задачи

Практическое руководство. Прием событий в приложениях Web Forms

Практическое руководство. Прием событий в приложениях Windows Forms

Основные понятия

События и делегаты

Вызов события

Другие ресурсы

Обработка и вызов событий