用winform程序來了解委托和事件


一、淺談委托

如果有個過winform 和webform 程序開發的小伙伴一定有個這樣的感覺吧,點擊Button直接就執行了那個方法,到此他是怎么實現了的呢,大家有考慮過沒有?

回到正題,什么是委托呢?委托,我們可以把看着是一個作為方法參數的一個方法,為什么呢,因為委托可以作為作為方法的參數,而給委托賦的值都是方法。下面我舉一個例 

   /// <summary>
   /// 定義的一個打招呼的委托 /// </summary> /// <param name="name"></param> public delegate void GreetingDelegate(string name); /// <summary> /// 中國人打招呼的類 /// </summary> public class Chinese { public void ChineseGreeting(string name) { Console.Write("早上好--" + name); } } public class English { public void EnglishGreeting(string name) { Console.Write("Good Morning--" + name); } } class Program { static void Main(string[] args) { Chinese people1 = new Chinese(); English people2 = new English(); Greeting("歡大少", people1.ChineseGreeting); Console.Write("\n"); Greeting("Master", people2.EnglishGreeting); Console.ReadKey(); } private static void Greeting(string name,GreetingDelegate MakingGreeting ) { MakingGreeting(name); } }

運行結果 

 

當然,實質上委托是一個特殊的類,知識有限,只能講到這兒了,

事件是什么呢,其實事件就是用event修飾后的委托,

   class Program
    {
        static void Main(string[] args)
        {
            Publishser pb = new Publishser();
            Subscriber sb = new Subscriber();
            //pb.NumberChange += sb.OnNumberChange;
            pb.NumberChange = sb.OnNumberChange;
            pb.DoSomething();
            pb.NumberChange(100);
            Console.ReadLine();
        }
    }

    /// <summary>
    /// 定義委托
    /// </summary>
    public  delegate void NumberChangeEventHandler(int count);

    public class Publishser
    {
        private int count;
        public NumberChangeEventHandler NumberChange;
        //public event NumberChangeEventHandler NumberChange;
        public void DoSomething()
        {
            if(NumberChange!=null)
            {
                count++;
                NumberChange(count);
            }
        }
    }

    public class Subscriber
    {
        public void OnNumberChange(int count) 
        {
            Console.WriteLine("Subscriber notified count ={0}", count);
        }
    }

上面的代碼如果是定義普通的委托能夠正常運行,但如果換成事件來的話變異不能通過,為什么呢?因為為了更好的封裝性,實際是事件是一個私有變量,外部不是訪問,如果用委托變量,外部能夠調用委托,影響封裝性,就像上面代碼

pb.NumberChange(100);,如果定義為事件,那么NumberChange只能通過內部方法DoSomething來調用。

 事件只能通過+=來進行賦值,如果你反編譯你可以看到事件里有兩個方法 Add() 和Remove(),分別對應的是+=和-=。

二、winform程序click事件的原理

在form的構造函數中,我們能看到下面的代碼

     /// <summary>
        /// 設計器支持所需的方法 - 不要
        /// 使用代碼編輯器修改此方法的內容。
        /// </summary>
        private void InitializeComponent()
        {
            this.button1 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // button1
            // 
            this.button1.Location = new System.Drawing.Point(391, 117);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 0;
            this.button1.Text = "button1";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(808, 400);
            this.Controls.Add(this.button1);
            this.Name = "Form1";
            this.Text = "F1";
            this.ResumeLayout(false);

        }

 

我們發現對事件的添加 this.button1.Click += new System.EventHandler(this.button1_Click);

這個地方我們只是添加了事件,但這個事件是怎么觸發的呢?我們進行調試

 

 

 

 button的click的觸發經過如下過程

 

三、模擬winform事件

 

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MonitorEvent
{
    /// <summary>
    /// 定義委托
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void MonitorEventHandler(object sender, EventArgs e);

    /// <summary>
    /// 時間數據類
    /// </summary>
    public class MsgEventArgs : EventArgs
    {
        /// <summary>
        /// 修改時間
        /// </summary>
        public DateTime ChanggeTime { get; set; }
        
        /// <summary>
        /// 提示信息
        /// </summary>
        public string ToSend { get; set; }
        public MsgEventArgs(DateTime changgeTime, string toSend)
        {
            this.ChanggeTime = changgeTime;
            this.ToSend = toSend;
        }
    }
    /// <summary>
    /// 事件訂閱者
    /// </summary>
    public class MonitorText
    {
        public string name = "文本文檔";
        //定義監控文本事件
        public event MonitorEventHandler MonitorEvent;
        //上次文件更新時間用於判斷文件是否修改過
        private DateTime _lastWriteTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
        public MonitorText()
        {

        }
        // 文件更新調用
        protected virtual void OnTextChange(MsgEventArgs e)
        {
            if (MonitorEvent != null)
            {
                //不為空,處理事件
                MonitorEvent(this, e);
            }
        }

        //事件監聽的方法
        public void BeginMonitor()
        {
            DateTime bCurrentTime;

            while (true)
            {
                bCurrentTime = File.GetLastWriteTime(@"C:\Users\Administrator\Desktop\1.txt");
                if (bCurrentTime != _lastWriteTime)
                {
                    _lastWriteTime = bCurrentTime;
                    MsgEventArgs msg = new MsgEventArgs(bCurrentTime, "文本改變了");
                    OnTextChange(msg);
                }
                //0.1秒監控一次
                Thread.Sleep(100);
            }
        }

    }

    /// <summary>
    /// 事件監聽者
    /// </summary>
    public class Administrator
    {
        //管理員事件處理方法
        public void OnTextChange(object Sender, EventArgs e)
        {
            MonitorText monitorText = (MonitorText)Sender;
            Console.WriteLine("尊敬的管理員:" + DateTime.Now.ToString() + ": " + monitorText.name + "發生改變.");
        }
    }

    class Program
    {
        static MonitorText MonitorTextEventSource;
        static void Main(string[] args)
        {
            MonitorTextEventSource = new MonitorText();
            //1. 啟動后台線程添加監視事件
            var thrd = new Thread(MonitorTextEventSource.BeginMonitor);
            thrd.IsBackground = true;
            thrd.Start();
            //2實例化管理員類
            Administrator ad = new Administrator();
            //4訂閱事件
            MonitorTextEventSource.MonitorEvent += ad.OnTextChange;
            Console.ReadLine();
        }
    }
}

四、申明

文中的觀點多來源與張子陽的.net之美和ATtuing的博客,希望大家共同學習

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM