Csharp/CSharp Tutorial/GUI Windows Forms/event

Материал из .Net Framework эксперт
Перейти к: навигация, поиск

A .NET-compatible event

<source lang="csharp">using System;

// Derive a class from EventArgs. class MyEventArgs : EventArgs {

 public int eventnum; 

}

// Declare a delegate for an event. delegate void MyEventHandler(object source, MyEventArgs arg);

// Declare an event class. class MyEvent {

 static int count = 0; 

 public event MyEventHandler SomeEvent; 

 // This fires SomeEvent. 
 public void OnSomeEvent() { 
   MyEventArgs arg = new MyEventArgs(); 

   if(SomeEvent != null) { 
     arg.eventnum = count++; 
     Console.WriteLine("Event fired");
     SomeEvent(this, arg); 
   } 
 } 

}

class X {

 public void handler(object source, MyEventArgs arg) { 
   Console.WriteLine("Event " + arg.eventnum + " received by an X object."); 
   Console.WriteLine("Source is " + source); 
   Console.WriteLine(); 
 } 

}

class Y {

 public void handler(object source, MyEventArgs arg) { 
   Console.WriteLine("Event " + arg.eventnum + " received by a Y object."); 
   Console.WriteLine("Source is " + source); 
   Console.WriteLine(); 
 } 

}

class MainClass {

 public static void Main() {  
   X ob1 = new X(); 
   Y ob2 = new Y(); 
   MyEvent evt = new MyEvent(); 

   // Add handler() to the event list. 
   evt.SomeEvent += ob1.handler; 
   evt.SomeEvent += ob2.handler; 

   // Fire the event. 
   evt.OnSomeEvent(); 
   evt.OnSomeEvent(); 
 } 

}</source>

Event fired
Event 0 received by an X object.
Source is MyEvent
Event 0 received by a Y object.
Source is MyEvent
Event fired
Event 1 received by an X object.
Source is MyEvent
Event 1 received by a Y object.
Source is MyEvent

Event and event handler

<source lang="csharp">using System; using System.Collections.Generic; using System.Reflection; using System.Runtime.InteropServices; class MyClass : IDisposable {

   public event EventHandler OnInitialized;
   public event EventHandler OnDisposed;
   public void Init()
   {
       // Initialize our state...
       EventHandler onInit = OnInitialized;
       if (onInit != null)
           onInit(this, new EventArgs());
   }
   public void Dispose()
   {
       // Release our state...
       EventHandler onDisp = OnDisposed;
       if (onDisp != null)
           onDisp(this, new EventArgs());
   }

} public class MainClass {

  public static void Main(){
       using (MyClass f = new MyClass())
       {
           f.OnInitialized += delegate { Console.WriteLine("init"); };
           f.OnDisposed += delegate { Console.WriteLine("disposed"); };
           f.Init();
       }            
  }

}</source>

init
disposed

Events

  1. Event handlers are represented by delegates.
  2. Events are members of a class
  3. Events are declared using the event keyword.

Its most commonly used form is shown here:


<source lang="csharp">event event-delegate object;</source>

  1. event-delegate is the name of the delegate used to support the event.
  2. object is the name of the specific event object being created.

Events: add and remove functions

<source lang="csharp">using System; public class Button {

   public delegate void ClickHandler(object sender, EventArgs e);
   
   public event ClickHandler Click;
   
   protected void OnClick()
   {
       if (Click != null)
       Click(this, null);
   }
   
   public void DoClick()
   {
       OnClick();
   }

} class MainClass {

   static public void ButtonHandler(object sender, EventArgs e)
   {
       Console.WriteLine("Button clicked");
   }
   
   public static void Main()
   {
       Button button = new Button();
       
       button.Click += new Button.ClickHandler(ButtonHandler);
       
       button.DoClick();
       
       button.Click -= new Button.ClickHandler(ButtonHandler);
       
       button.DoClick();
   }

}</source>

Button clicked

Events: add and remove functions for a private delegate event

<source lang="csharp">using System; public class Button {

   public delegate void ClickHandler(object sender, EventArgs e);
   private ClickHandler click;
   
   public void AddClick(ClickHandler clickHandler)
   {
       click += clickHandler;
   }
   
   public void RemoveClick(ClickHandler clickHandler)
   {
       click -= clickHandler;
   }
   
   protected void OnClick()
   {
       if (click != null)
       click(this, null);
       
   }
   
   public void DoClick()
   {
       OnClick();
   }

} class MainClass {

   static public void ButtonHandler(object sender, EventArgs e)
   {
       Console.WriteLine("Button clicked");
   }
   
   public static void Main()
   {
       Button button = new Button();
       
       button.AddClick(new Button.ClickHandler(ButtonHandler));
       
       button.DoClick();
       
       button.RemoveClick(new Button.ClickHandler(ButtonHandler));
       
       button.DoClick();
   }

}</source>

Button clicked

Events add and remove with synchronized block

<source lang="csharp">using System; using System.Collections; using System.Runtime.rupilerServices; public class Button {

   public delegate void ClickHandler(object sender, EventArgs e);
   
   Hashtable delegateStore = new Hashtable();
   static object clickEventKey = new object();
   
   public event ClickHandler Click
   {
       [MethodImpl(MethodImplOptions.Synchronized)]
       add
       {
           delegateStore[clickEventKey] =
           Delegate.rubine((Delegate) delegateStore[clickEventKey],
           value);
       }
       
       [MethodImpl(MethodImplOptions.Synchronized)]
       remove
       {
           delegateStore[clickEventKey] =
           Delegate.Remove((Delegate) delegateStore[clickEventKey],
           value);
       }
   }
   
   protected void OnClick()
   {
       ClickHandler ch = (ClickHandler) delegateStore[clickEventKey];
       if (ch != null)
       ch(this, null);
   }
   
   public void DoClick()
   {
       OnClick();
   }

} class MainClass {

   static public void ButtonHandler(object sender, EventArgs e)
   {
       Console.WriteLine("Button clicked");
   }
   
   public static void Main()
   {
       Button button = new Button();
       
       button.Click += new Button.ClickHandler(ButtonHandler);
       
       button.DoClick();
       
       button.Click -= new Button.ClickHandler(ButtonHandler);
       
       button.DoClick();
   }

}</source>

Button clicked

Events and form controls

<source lang="csharp">using System; using System.Collections.Generic; using System.ruponentModel; using System.Data; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms;

   public class Events : Form
   {
       public Events()
       {
           InitializeComponent();
       }
       private void button1_Click(object sender, EventArgs e)
       {
           MessageBox.Show("I have been Clicked");
       }
       private void textBox1_MouseEnter(object sender, EventArgs e)
       {
           label1.Text = "Mouse Enters into the TextBox";            
       }
       private void textBox1_MouseLeave(object sender, EventArgs e)
       {
           label1.Text = "Mouse Leaves the TextBox";            
       }
       private void textBox1_KeyDown(object sender, KeyEventArgs e)
       {
           if (e.Alt == true)
               label1.Text="The ALT has been pressed";
           else
               if (e.Control==true)
                   label1.Text="The Ctrl has been pressed";
               else
                   if (e.Shift==true)
                   label1.Text="The Shift has been pressed";                
       }
       private void textBox1_KeyUp(object sender, KeyEventArgs e)
       {
           if (e.Alt == false || e.Control==false || e.Shift==false) 
               label1.Text = "The Key has been released";                    
       }
       private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
       {
           if (char.IsDigit(e.KeyChar)==true)
                 label1.Text = "You have pressed a Numeric key";
              else
                 if(char.IsLetter(e.KeyChar)==true)
                 label1.Text = "You have pressed a Letter key";
           
              
       }                
       private void InitializeComponent()
       {
           this.button1 = new System.Windows.Forms.Button();
           this.textBox1 = new System.Windows.Forms.TextBox();
           this.label1 = new System.Windows.Forms.Label();
           this.SuspendLayout();
           // 
           // button1
           // 
           this.button1.Location = new System.Drawing.Point(94, 23);
           this.button1.Name = "button1";
           this.button1.Size = new System.Drawing.Size(75, 23);
           this.button1.TabIndex = 0;
           this.button1.Text = "Click Me";
           this.button1.UseVisualStyleBackColor = true;
           this.button1.Click += new System.EventHandler(this.button1_Click);
           // 
           // textBox1
           // 
           this.textBox1.Location = new System.Drawing.Point(81, 78);
           this.textBox1.Multiline = true;
           this.textBox1.Name = "textBox1";
           this.textBox1.Size = new System.Drawing.Size(103, 70);
           this.textBox1.TabIndex = 1;
           this.textBox1.MouseLeave += new System.EventHandler(this.textBox1_MouseLeave);
           this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyDown);
           this.textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyUp);
           this.textBox1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.textBox1_KeyPress);
           this.textBox1.MouseEnter += new System.EventHandler(this.textBox1_MouseEnter);
           // 
           // label1
           // 
           this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
           this.label1.Location = new System.Drawing.Point(12, 169);
           this.label1.Name = "label1";
           this.label1.Size = new System.Drawing.Size(268, 23);
           this.label1.TabIndex = 2;
           this.label1.Text = "label1";
           this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
           // 
           // Events
           // 
           this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
           this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
           this.ClientSize = new System.Drawing.Size(292, 273);
           this.Controls.Add(this.label1);
           this.Controls.Add(this.textBox1);
           this.Controls.Add(this.button1);
           this.Name = "Events";
           this.Text = "Events";
           this.ResumeLayout(false);
           this.PerformLayout();
       }
       private System.Windows.Forms.Button button1;
       private System.Windows.Forms.TextBox textBox1;
       private System.Windows.Forms.Label label1;
       
       [STAThread]
       static void Main()
       {
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);
           Application.Run(new Events());
       }
   }</source>

Events: Custom Add and Remove with Global delegate cache.

<source lang="csharp">// copyright 2000 Eric Gunnerson // From A Programmer"s Introduction to C# 2.0, Third Edition using System; using System.Collections; using System.Runtime.rupilerServices; // // Global delegate cache. Uses a two-level hashtable. The delegateStore hashtable // stores a hashtable keyed on the object instance, and the instance hashtable is // keyed on the unique key. This allows fast tear-down of the object when it"s destroyed. // public class DelegateCache {

   private DelegateCache() {}    // nobody can create one of these
   
   Hashtable delegateStore = new Hashtable();    // top level hash table
   
   static DelegateCache dc = new DelegateCache();    // our single instance
   
   Hashtable GetInstanceHash(object instance)
   {
       Hashtable instanceHash = (Hashtable) delegateStore[instance];
       
       if (instanceHash == null)
       {
           instanceHash = new Hashtable();
           delegateStore[instance] = instanceHash;
           
       }
       return(instanceHash);
   }
   
   public static void Combine(Delegate myDelegate, object instance, object key)
   {
       lock(instance)
       {
           Hashtable instanceHash = dc.GetInstanceHash(instance);        
           
           instanceHash[key] = Delegate.rubine((Delegate) instanceHash[key],
           myDelegate);
       }
   }
   
   public static void Remove(Delegate myDelegate, object instance, object key)
   {
       lock(instance)
       {
           Hashtable instanceHash = dc.GetInstanceHash(instance);        
           
           instanceHash[key] = Delegate.Remove((Delegate) instanceHash[key],
           myDelegate);
       }
   }
   
   public static Delegate Fetch(object instance, object key)
   {
       Hashtable instanceHash = dc.GetInstanceHash(instance);        
       
       return((Delegate) instanceHash[key]);
   }
   
   public static void ClearDelegates(object instance)
   {
       dc.delegateStore.Remove(instance);
   }

} public class Button {

   public void TearDown()
   {
       DelegateCache.ClearDelegates(this);
   }
   
   
   public delegate void ClickHandler(object sender, EventArgs e);
   
   static object clickEventKey = new object();
   
   public event ClickHandler Click
   {
       add
       {
           DelegateCache.rubine(value, this, clickEventKey);
       }
       
       remove
       {
           DelegateCache.Remove(value, this, clickEventKey);
       }
   }
   
   protected void OnClick()
   {
       ClickHandler ch = (ClickHandler) DelegateCache.Fetch(this, clickEventKey);
       
       if (ch != null)
       ch(this, null);
   }
   
   public void SimulateClick()
   {
       OnClick();
   }

} class Test {

   static public void ButtonHandler(object sender, EventArgs e)
   {
       Console.WriteLine("Button clicked");
   }
   
   public static void Main()
   {
       Button button = new Button();
       
       button.Click += new Button.ClickHandler(ButtonHandler);
       
       button.SimulateClick();
       
       button.Click -= new Button.ClickHandler(ButtonHandler);
       
       button.TearDown();
   }

}</source>

Button clicked

Fire event in property setter

<source lang="csharp">using System; public class SalaryEvent : EventArgs {

 public string Message;
 public SalaryEvent(string message)
 {
   this.Message = message;
 }

} public class Employee {

 private int salary;
 public delegate void SalaryTaxEventHandler( object reactor, SalaryEvent myEvent );
 public event SalaryTaxEventHandler OnTax;
 public int Salary
 {
   set
   {
     salary = value;
     if (salary > 1000)
     {
       SalaryEvent myEvent = new SalaryEvent("Employee meltdown in progress!");
       OnTax(this, myEvent);
     }
   }
 }

} public class EmployeeMonitor {

 public EmployeeMonitor(Employee myEmployee)
 {
   myEmployee.OnTax += new Employee.SalaryTaxEventHandler(DisplayMessage);
 }
 public void DisplayMessage( object myEmployee, SalaryEvent myEvent )
 {
   Console.WriteLine(myEvent.Message);
 }

}

class MainClass {

 public static void Main()
 {
   Employee myEmployee = new Employee();
   EmployeeMonitor myEmployeeMonitor = new EmployeeMonitor(myEmployee);
   myEmployee.Salary = 100;
   myEmployee.Salary = 500;
   myEmployee.Salary = 2000;
 }

}</source>

Employee meltdown in progress!

Ignored Parameters Anonymous Methods for Button click, kepressed and mouse clicked action

<source lang="csharp">using System; using System.Windows.Forms; using System.ruponentModel;

   class MainClass
   {
       static void Main()
       {
           Button button = new Button();
           button.Text = "Click me";
           button.Click += delegate { Console.WriteLine("LogPlain"); };
           button.KeyPress += delegate { Console.WriteLine("LogKey"); };
           button.MouseClick += delegate { Console.WriteLine("LogMouse"); };
           Form form = new Form();
           form.AutoSize = true;
           form.Controls.Add(button);
           Application.Run(form);
       }
   }</source>

Use an anonymous method as an event handler

<source lang="csharp">using System;

delegate void MyEventHandler();

class MyEvent {

 public event MyEventHandler SomeEvent;  
 
 public void OnSomeEvent() {  
   if(SomeEvent != null)  
     SomeEvent();  
 }  

}

class MainClass {

 public static void Main() {   
   MyEvent evt = new MyEvent();  
 
   // Use an anonymous method as an event handler. 
   evt.SomeEvent += delegate  {  
     // This is the event handler. 
     Console.WriteLine("Event received.");  
   }; 

   evt.OnSomeEvent();  
   evt.OnSomeEvent();  
 }  

}</source>

Event received.
Event received.

Use delegate to handle events

<source lang="csharp">using System; public class Button {

   public delegate void ClickHandler(object sender, EventArgs e);
   public ClickHandler Click;
   
   protected void OnClick()
   {
       if (Click != null)
          Click(this, null);
   }
   
   public void DoClick()
   {
       OnClick();
   }

} class MainClass {

   static public void ButtonHandler(object sender, EventArgs e)
   {
       Console.WriteLine("Button clicked");
   }
   
   public static void Main()
   {
       Button button = new Button();
       
       button.Click = new Button.ClickHandler(ButtonHandler);
       
       button.DoClick();
   }

}</source>

Button clicked

Use the built-in EventHandler delegate

<source lang="csharp">using System;

// Declare an event class. class MyEvent {

 public event EventHandler SomeEvent; // uses EventHandler delegate 

 // This is called to fire SomeEvent. 
 public void OnSomeEvent() { 
   if(SomeEvent != null) 
     SomeEvent(this, EventArgs.Empty); 
 } 

}

class MainClass {

 static void handler(object source, EventArgs arg) { 
   Console.WriteLine("Event occurred"); 
   Console.WriteLine("Source is " + source); 
 } 

 public static void Main() {  
   MyEvent evt = new MyEvent(); 

   // Add handler() to the event list. 
   evt.SomeEvent += handler; 

   // Fire the event. 
   evt.OnSomeEvent(); 
 } 

}</source>

Event occurred
Source is MyEvent

Using Event Accessors

  1. You can use event accessors to take control of the event handler list.
  2. The accessors specify how the event handler list is implemented.

This form is shown here:


<source lang="csharp">event event-delegate event-name {

       add {
           // code to add an event to the chain
       }
       
       remove {
           // code to remove an event from the chain
       }
   }</source>