zoukankan      html  css  js  c++  java
  • C#学习笔记-事件基础

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Timers;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Event1
    {
    #if false
    1、Event的普通定义就是“能够发生什么事情, a thing that happens, especially something important!2、C#中的事件的定义:使对象或类具备通知能力的成员
    3、作用:用于对象或类间动作协调与信息传递(消息推送)
    4、原理:事件模型(也叫“发生-响应”模型)
         5个部分:eg:闹钟响了你起床,可以分解为5部分:(1)闹钟(事件的发出者/拥有者 event source) (2)响铃(事件event,可以附带一些信息即事件参数) ---(3)订阅(subscribe 你关心了闹铃事件)--- (4)你(事件订阅者/响应者event subscriber) (5)起床(对事件的响应,也叫处理事件或事件处理器 event handler)
         5个动作:(1)我有一个事件 (2)一个人或一群人关心我这个事件 (3)我这个事件发生了 (4)关心这个事件的人会依次得到通知 (5)收到通知的人根据拿到的事件信息(又称事件参数/数据)对事件进行响应(处理事件)
    5、常用场景
        GUI编程
        MVC MVP MVVM是事件模型的升级
        绝大部分情况下都不需要自己定义事件,都是使用预定义的事件
    6、事件和委托的关系
        委托只是事件和事件处理器之间的的一种调用约定
    #endif
        class Program
        {
            static void Main(string[] args)
            {
                // 类最重要的三个部分(存储数据、做事情、通知别人)
                // 属性:表示当前对象的状态
                // 事件:表示对象能在什么情况下通知谁
                // 方法:表示当前对象能做什么
    
    #if true
                // 模型1 *:(事件的拥有者、事件) 和 (事件订阅者、事件处理器) 两大部分分别独立,这是最基础的模型,也是MVC这些模式的雏形
                // event source
                System.Timers.Timer timer = new System.Timers.Timer();  // Forms命名空间里面也有Timer,这里是为了解决冲突写明确指明是System.Timers下的Timer
                timer.Interval = 1000; // 1000ms
                // event subscribers
                Subscriber1 sub1 = new Subscriber1();
                Subscriber2 sub2 = new Subscriber2();
                // event --- +=(subscribe) --- event handler
                timer.Elapsed += sub1.TimerEventHandler;
                timer.Elapsed += sub2.TimerEventHandler;
                // event source开始工作,每隔1000ms发出Elapsed事件通知
                timer.Start();
    #endif
    
    #if true
                // 模型2 ***:(事件订阅者、事件处理器) 内部包含 (事件的拥有者、事件) ,这是典型的GUI中常用模型,
                // 比如 主窗口(按钮点击事件的订阅者)里面有一个按钮控件(event source) 订阅(subscribe) 按钮的点击事件(event) 并且拥有按钮点击事件的处理方法(event handler)
                MainForm mainForm = new MainForm();
                mainForm.ShowDialog();
    #endif
    
    #if false
                // 模型3 **:事件订阅者和拥有者是同一个对象,事件 和 事件处理器都属于该对象,即自己使用自己的事件处理器处理自己的事件
                MyForm form = new MyForm();
                form.Click += form.FormClicked;
                form.ShowDialog();
    #endif
    
                Console.ReadLine();
            }
        }
    
        class Subscriber1
        {
            internal void TimerEventHandler(object sender, ElapsedEventArgs e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Subscriber1 handing timer's elapsed event!");
            }
        }
    
        class Subscriber2
        {
            internal void TimerEventHandler(object sender, ElapsedEventArgs e)
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Subscriber2 handing timer's elapsed event!");
            }
        }
    
        class MainForm : Form
        {
            public MainForm()
            {
                this.Text = "MainForm";
                this.Width = 400;
                this.Height = 300;
                this.FormBorderStyle = FormBorderStyle.FixedDialog;
                this.MaximizeBox = false;
    
                this.textBox = new TextBox();
                this.textBox.Top = 5;
                this.textBox.Width = this.Width - 10;
                this.textBox.Height = 25;
    
                this.button = new Button();
                this.button.Top = 10 + this.textBox.Height;
                this.button.Width = this.Width - 10;
                this.button.Text = "Button1";
    
                this.oldButton = new Button();
                this.oldButton.Top = this.button.Top + this.button.Height + 5;
                this.oldButton.Width = this.Width - 10;
                this.oldButton.Text = "Button2";
    
                this.Controls.Add(this.textBox);
                this.Controls.Add(this.button);
                this.Controls.Add(this.oldButton);
    
                // MainForm 订阅 button成员 的 Click 事件 安装的事件处理器为 ButtonClicked
                this.button.Click += this.ButtonClicked;
    
    
                // 一些事件处理器的旧式写法即显式使用委托的方式
                //this.oldButton.Click += new EventHandler(OldButton_Click); // EventHandler是一个委托类型,现在直接传一个方法给它也将自动生成对应的委托,就跟上面那样
                //this.oldButton.Click += delegate (object sender, EventArgs e)
                //{
                //    // 这说白了就是个匿名委托
                //    this.textBox.Text = "MainForm's Button2 Clicked!";
                //};
    
                // 新式的Lambda表达式,甚至可以不写参数的类型,编译器会根据Click事件处理器对应的委托约束 (选中Click按下F12可以跳转) 来正确推导类型
                this.oldButton.Click += (object sender, EventArgs e) =>
                {
                    this.textBox.Text = "MainForm's Button2 Clicked!";
                };
            }
    
            private void OldButton_Click(object sender, EventArgs e)
            {
                this.textBox.Text = "MainForm's Button2 Clicked!";
            }
    
            // 按钮点击事件的处理器
            private void ButtonClicked(object sender, EventArgs e)
            {
                this.textBox.Text = "MainForm's Button1 Clicked!";
            }
    
            private TextBox textBox;
            private Button button; // 事件的拥有者event source,它是事件订阅者MainForm的一个成员
            private Button oldButton;
        }
    
        class MyForm : Form
        {
            internal void FormClicked(object sender, EventArgs e)
            {
                MessageBox.Show("Form Clicked!");
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace Event2
    {
        class Program
        {
            static void Main(string[] args)
            {
                // 事件拥有者
                Customer customer = new Customer();
    
                // 事件订阅者
                Water water = new Water();
    
                // 订阅事件、添加事件处理器
                customer.Order += water.Action;
                // customer.Order.Invoke // error 这就是为什么需要事件的原因,如果Order是一个委托,则它可以在外面任意调用,但是事件类型在外部是只能出现在 += 左边,不允许其他操作
                // 此时如果是委托,那么别的一个顾客就可以帮一个不认识的顾客瞎点菜,即 customer2.Order.Invoke(customer, e);
    
                // 由事件拥有者在某些条件下触发事件
                customer.Action();
                customer.PayTheBill();
            }
        }
    
        public class OrderEventArgs : EventArgs
        {
            public string DishName { get; set; }
            public string Size { get; set; }
        }
    
    
        // 约束事件和事件处理器的委托类型(即约束返回值、参数)
        public delegate void OrderEventHandler(Customer sender, OrderEventArgs e); 
    
    
        // 事件拥有者
        public class Customer
        {
    #if false
            // 完整声明形式:
    
            // 用于保存事件处理器(处理器也是受 OrderEventHandler 委托类型约束)
            private OrderEventHandler orderEventHandler;
    
            // 声明事件(使用 OrderEventHandler 委托类型作为约束条件)
            public event OrderEventHandler Order
            {
                add
                {
                    this.orderEventHandler += value; // 添加事件处理器
                }
    
                remove
                {
                    this.orderEventHandler -= value;// 删除事件处理器
                }
            } 
    #endif
    
            // 事件的简单声明形式(编译器在后台自动创建了OrderEventHandler委托类型的字段)
            public event OrderEventHandler Order;
    
            public double Bill { get; set; }
    
            public void PayTheBill()
            {
                Console.WriteLine("Pay the bill ${0}", this.Bill);
            }
    
            public void WalkIntoRestaurant()
            {
                Console.WriteLine("Customer walk into the restaurant...");
            }
    
            public void SitDown()
            {
                Console.WriteLine("Customer sit down...");
            }
    
            public void BrowseDishMenu()
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                for (int i = 0; i < 5; ++i)
                {
                    Console.WriteLine("Browsing and choosing...");
                    Thread.Sleep(1000);
                }
    
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Choose ok! Need a water...");
    
    #if false
                // 使用完整声明时:
                // 判断是否有事件处理器
                if (this.orderEventHandler != null)
                {
                    OrderEventArgs e = new OrderEventArgs() { DishName = "Kongpao Chicken", Size = "normal" };
                    this.orderEventHandler.Invoke(this, e); // 触发事件
                }
    #endif
    
                // 使用简单声明时
                if (this.Order != null)
                {
                    OrderEventArgs e = new OrderEventArgs() { DishName = "Kongpao Chicken", Size = "normal" };
                    this.Order.Invoke(this, e); // 触发事件
                }
            }
    
            public void Action()
            {
                WalkIntoRestaurant();
    
                SitDown();
    
                BrowseDishMenu();
            }
        }
    
    
        // 事件订阅者
        public class Water
        {
            public void Action(Customer customer, OrderEventArgs e)
            {
                Console.ForegroundColor = ConsoleColor.Blue;
                Console.WriteLine("Water: a new dish:{0}", e.DishName);
    
                double price = 10.0;
    
                switch (e.Size)
                {
                    case "small":
                        price = price * 0.5;
                        break;
                    case "normal":
                        price = price * 1.0;
                        break;
                    case "big":
                        price = price * 1.5;
                        break;
                    default:
                        break;
                }
    
                customer.Bill += price;
            }
        }
    }
  • 相关阅读:
    表优化
    存储和压缩
    自定义函数
    Hadoop中SecondaryNameNode和HA(高可用)区别
    ASUS笔记本,更换了固态硬盘,重装系统前后开机都自动进入BIOS界面
    顶部下拉菜单制作笔记
    综合笔记
    工具sublime安装
    head引入样式
    滚动固定导航代码
  • 原文地址:https://www.cnblogs.com/djh5520/p/14680161.html
Copyright © 2011-2022 走看看