[C#] 事件 (Events)

  • 34012
  • 0
  • 2009-12-29

摘要:[C#] 事件

Introduction

事件本身代表某種動作被執行,例如 button 被使用者按下,textbox 輸入文字..等

事件由類別所產生,其他物件或方法處理器因此被通知處理所觸發的事件,而其間的

關聯則透過委派物件來完成。

撰寫事件處理程式步驟如下:

  • 宣告委派型別
  • 定義 System.EventArgs 類別的衍生類別,儲存事件相關資訊
  • 使用關鍵字 Event  宣告事件
  • 定義事件處理程式之方法成員
  • 使用委派物件封裝方法成員
  • 引用委派方法處理觸發事件

其中建立事件的語法:

  • event delegateName eventObject

event : 關鍵字

eventObject : 事件變數

delegateName : 支援此事件的委派名稱

 

Example

sample1

非標準版本

using System;

//宣告一個委派型別:無回傳值,無任何參數。
delegate void DlgDoCalcDelegate() ;

class calc {
    //宣告一個由 DlgDoCalcDelegate 委派所支援的事件
    public event DlgDoCalcDelegate evtDoCalc;

    //定義觸發此事件的方法
    public void DoCalc() {
        evtDoCalc();
    }
}

class EventsHandler
{
    //定義事件處理程式方法成員
	private  void DoAdd() 
	{
		AddMethod() ; 
	}	

    
	private void AddMethod() 
	{
		long lngFirstValue ; 
		long lngSecondValue ;	

		long lngSum ; 
		Console.WriteLine ("請輸入第一個進行運算數值 :") ; 
		lngFirstValue = long.Parse(Console.ReadLine()) ; 

		Console.WriteLine ("請輸入第二個進行運算數值 :") ;
		lngSecondValue =  long.Parse(Console.ReadLine()) ;
        lngSum = lngFirstValue + lngSecondValue; 

		Console.WriteLine
			("{0} 與 {1} 的加總等於 {2} " , lngFirstValue,lngSecondValue,lngSum) ; 
	}
	
	static void Main()
	{
		EventsHandler myEventsHandler = new EventsHandler() ; 
		calc mycalc =  new calc() ; 
        //將 DoAdd 方法於 evtDoCalc 事件中註冊
		mycalc.evtDoCalc += new DlgDoCalcDelegate(myEventsHandler.DoAdd) ; 
		Console.WriteLine ("觸發加法運算事件 …") ;

        //觸發事件。
		mycalc.DoCalc() ; 	
		Console.Read() ; 
	}
}

執行結果

 

 sample2

上面範例所示,我可以自訂任何方法支援觸發事件,然而,這不是最好的,

最好是符合 .net 事件處理方法的準則。以下我們觀察表單事件。

public Form1() {
            InitializeComponent();
            //訂閱表單 Click 事件
            this.Click += new EventHandler(Form1_Click);
        }

        //當表單事件被觸發後,會執行這個 Method
        void Form1_Click(object sender, EventArgs e) {
            //Do Something
        }

其中

sender : 代表觸發此事件的來源物件

e : 則包含了事件相關資訊的 EventArgs 類別物件,是其他事件類別的基底類別

reference :http://msdn.microsoft.com/zh-tw/library/ms229011%28VS.80%29.aspx

標準版本

using System;

//定義 SpeedCheckEventArgs 繼承 EventArgs
public class SpeedCheckEventArgs : EventArgs {
    //撰寫該事件相關資訊
    private long speed;
    public SpeedCheckEventArgs(long speed) {
        this.speed = speed;
    }
    public long getSpeed {
        get { return speed; }
    }
    public string WarningMessage {
        get {
            return ("警告 : 行車超過速限 !!");
        }
    }
}

//定義委派型別,沒有回傳值,並且需要兩個參數傳入
public delegate void SpeedCheckHandler(object sender, SpeedCheckEventArgs e);


public class CheckSpeed {
    //定義符合 SpeedCheckHandler 委派的事件
    public event SpeedCheckHandler myEvent;

    public void CheckSpeedLimit(long speed) {
        if (speed > 60) {

            //建立 SpeedCheckEventArgs 物件。
            SpeedCheckEventArgs speedsArgs = new SpeedCheckEventArgs(speed);

            //觸發事件,傳入來源物件與事件物件。
            myEvent(this, speedsArgs);
        } else {
            Console.WriteLine("您目前的速度正常");
        }
    }
}

public class DoSomeThing {

    //定義 SlowDown 方法,傳入兩個參數,其中 e 為 SpeedCheckEventArgs 型別。
    public void SlowDown(object sender, SpeedCheckEventArgs e) {
        Console.WriteLine
            (e.WarningMessage);
        Console.WriteLine("您目前車速 {0} 已超速,請踩下煞車,降低速度,避免危險 !!", e.getSpeed);
        Console.WriteLine
            ("正常行車速度請降至 60 Km/hr 以下 !!");
    }
}

//主程式
public class Events {
    static void Main() {
        long speed;
        CheckSpeed myCheckSpeed = new CheckSpeed();
        DoSomeThing myDoSomeThing = new DoSomeThing();
        Console.Write("目前行車速度 : ");
        //取得使用者輸入數字
        speed = long.Parse(Console.ReadLine());

        Console.WriteLine("");

        //訂閱事件。
        myCheckSpeed.myEvent += new SpeedCheckHandler(myDoSomeThing.SlowDown);

        //檢查車速
        myCheckSpeed.CheckSpeedLimit(speed);

        Console.ReadLine();
    }
}

執行結果

2009-12-28_235749

 

sample3

若是事件處理過程,不需使用 EventArg 引數傳遞事件所包含的資訊,可以考慮直接使用 EventHandler 這個

.net 預設的委派型別。


    //定義一個計算類別
    class calc {
        //建立一個內鍵事件
        public event EventHandler evtDoCalc;

        //觸發事件
        public void DoCalc() {
            evtDoCalc(this, EventArgs.Empty);
        }
    }

    //主程式
    class Program {
        static void Main(string[] args) {
            Program myEventsHandler = new Program();
            calc mycalc = new calc();
            //繫結事件
            mycalc.evtDoCalc += new EventHandler(myEventsHandler.DoAdd);

            Console.WriteLine("觸發加法運算事件…");
            //開始做計算
            mycalc.DoCalc();
            Console.Read();
        }

        private void DoAdd(object o, EventArgs e) {
            Console.WriteLine("觸發事件的來源物件 : {0} \n", o.ToString());
            AddMethod();
        }

        //加法函式
        private void AddMethod() {
            long lngFirstValue;
            long lngSecondValue;

            long lngSum;
            Console.WriteLine("請輸入第一個進行運算數值 :");
            lngFirstValue = long.Parse(Console.ReadLine());

            Console.WriteLine("請輸入第二個進行運算數值 :");
            lngSecondValue = long.Parse(Console.ReadLine());
            lngSum = lngFirstValue + lngSecondValue;

            Console.WriteLine
                ("{0} 與 {1} 的加總等於 {2} ", lngFirstValue, lngSecondValue, lngSum);
        }
    }
}

執行結果

 

sample4

多重事件

//定義委派型別
delegate void MultiCastDel(int intx, int inty);

//加法類別
class AddCalc {
    public void DoAdd(int intx, int inty) {
        int intResult;
        intResult = intx + inty;

        Console.WriteLine("物件 AddCalc 對兩個整數 {0},{1} 作加法運算 !!",
intx, inty);
        Console.WriteLine("執行運算結果等於 {0} \n", intResult);
    }
}

//減法類別
class SubCalc {
    public void DoSub(int intx, int inty) {
        int intResult;
        intResult = intx - inty;

        Console.WriteLine("物件 SubCalc 對兩個整數 {0},{1} 作減法運算 !!"
, intx, inty);
        Console.WriteLine("執行運算結果等於 {0} \n", intResult);
    }
}

//乘法類別
class MultiCalc {
    public void DoMul(int intx, int inty) {
        int intResult;
        intResult = intx * inty;

        Console.WriteLine("物件 MultiCalc 對兩個整數 {0},{1} 作乘法運算 !!", intx, inty);
        Console.WriteLine("執行運算結果等於 {0} \n", intResult);
    }
}

//除法類別
class DivCalc {
    public void DoDiv(int intx, int inty) {
        if (inty == 0) {
            Console.WriteLine("除數為 0 無法作除法運算 !!");
        } else {
            int intResult;
            intResult = intx / inty;

            Console.WriteLine("物件 DivCalc 對兩個整數 {0},{1} 作除法運算 !!", intx, inty);
            Console.WriteLine("執行運算結果等於 {0} \n", intResult);
        }
    }
}

//事件類別
class MultiEvent {
    int x;
    int y;
    public int px {
        set {
            x = value;
        }
    }
    public int py {
        set {
            y = value;
        }
    }

    //建立事件並且支援 MultiCastDel 委派
    public event MultiCastDel DoEvent;
    public void OnDoEvent() {
        DoEvent(x, y);
    }
}


//主程式
class MultiCastEvent {
    static void Main() {
        AddCalc myAddCalc = new AddCalc();
        SubCalc mySubCalc = new SubCalc();
        MultiCalc myMultiCalc = new MultiCalc();
        DivCalc myDivCalc = new DivCalc();

        MultiEvent myMultiEvent = new MultiEvent();
        myMultiEvent.px = 100;
        myMultiEvent.py = 100;

        myMultiEvent.DoEvent += new MultiCastDel(myAddCalc.DoAdd);
        myMultiEvent.DoEvent += new MultiCastDel(mySubCalc.DoSub);
        myMultiEvent.DoEvent += new MultiCastDel(myMultiCalc.DoMul);
        myMultiEvent.DoEvent += new MultiCastDel(myDivCalc.DoDiv);

        myMultiEvent.OnDoEvent();
        Console.ReadLine();
    }
}

執行結果

 

Link

三小俠  小弟獻醜,歡迎指教