Search…

Event trong C#

22/09/20204 min read
Giới thiệu và hướng dẫn cách hiện thực các event trong C#.

Giới thiệu

Thông thường khi mới bắt đầu lập trình giao diện Windows Forms Application, Windows Phone thường xuyên tiếp xúc với những sự kiện như Click của Button, TextChanged của Textblock. Những phương thức xử lý sự kiện tương ứng như:

void btnSubmit_Clicked(object sender, System.EventArgs e)

void txtContent_TextChanged(object sender, RoutedEventArgs e)

Bài viết này sẽ giới thiệu những sự kiện đó được xây dựng như thế nào và những đối số sender, e ở hai phương trên có ý nghĩa như thế nào.

Khai báo sự kiện

Bài viết sẽ lấy ví dụ là 1 sản phẩm (Product) có trường dữ liệu là giá của sản phẩm (Price). Khi mà trường dữ liệu này thay đổi thì sẽ phát sinh sự kiện và có các thông tin gửi kèm theo sự kiện là giá cũ và giá mới (OldPrice) và giá mới (NewPrice).

Để khai báo một sự kiện trước tiên tạo một delegate.

void delegate PriceChangedHandler(decimal oldPrice, decimal newPrice)

Khai báo sự kiện

public  delegate void PriceChangedHandler(decimal oldPrice, decimal newPrice);
public class Product
{
   public event PriceChangedHandler PriceChanged;  
}

Triển khai sự kiện

Phần trên đã khai báo sự kiện PriceChanged. Bây giờ sẽ đi tiếp phần tiếp theo là triển khai sự kiện này để khi giá (Price) thay đổi thì sẽ phát sinh sự kiện.

Khai báo trường dữ liệu của class Product

private decimal _price;

và triển khai sự kiện sử dụng getset

public class Product
{
    private decimal _price;
    public event PriceChangedHandler PriceChanged;  
    public decimal Price
    {
        get
        {
            return this._price;
        }
        set
        {
            if (_price == value)
                return;
            decimal oldPrice = _price;
            _price = value;
            if (PriceChanged != null)
                PriceChanged(oldPrice, _price);
        }
    }     
}

Triển khai hàm Main:

class Program
    {
        static void Main(string[] args)
        {
            Product product = new Product();
            product.Price = 10000;
            product.PriceChanged += product_PriceChanged;
            product.Price = 50000;
            Console.ReadLine();
        }

        static void product_PriceChanged(decimal oldPrice, decimal newPrice)
        {
            Console.WriteLine("Old Price: {0}", oldPrice);
            Console.WriteLine("New Price: {0}", newPrice);
        }
    }

Trong mô hình sự kiện có hai khai niệm cần quan tâm là đối tượng phát sinh sự kiện (Broadcaster), và phương thức xử lý sự kiện (Subscriber).

  • Broadcaster: kiểu chứa event, ở trên là Product. Hoặc có thể là Button, Textblock, Combobox.
  • Subscriber: phương thức đăng ký và xử lý sự kiện do những đối tượng ở Broadcaster phát sinh.

Mô hình chuẩn sự kiện trong .NET

Nhiều khi cần phải tạo ra nhiều sự kiện, mỗi sự kiện có cách viết khác nhau, không đồng bộ. Để khắc phục nhược điểm đó thì .Net Framework có đưa là một mô hình chuẩn để viết sự kiện giúp cho việc viết sự kiện dễ dàng. Mô hình này như sau:

Khai báo delegate có quy tắc rằng buộc:

  • Delegate có kiểu trả về là kiểu void.
  • Delegate có hai tham số.
    • Tham số thứ nhất có kiểu là object là đối tượng phát sinh sự kiện.
    • Tham số thứ hai có kiểu EventArgs là class giữ thông tin mà đối tượng gửi kèm trong quá trình phát sinh sự kiện.

Class PriceChangedEventArgs

public class PriceChangedEventArgs
{
	public readonly decimal OldPrice;
	public readonly decimal NewPrice;
	
	public PriceChangedEventArgs(decimal oldPrice, decimal newPrice)
	{
		this.OldPrice = oldPrice;
		this.NewPrice = newPrice;
	}
}

Khai báo delegate

public delegate void PriceChangedHandler(object sender, PriceChangedEventArgs e);

Cuối cùng là tạo một phương thức virtual có phạm vi truy xuất là protect có nhiệm vụ phát sinh sự kiện.

protected virtual void OnPriceChanged(PriceChangedEventArgs e)
{
	if (PriceChanged != null)
		PriceChanged(this, e);
}

Triển khai sự kiện sử dụng get, set

public decimal Price
{
	get
	{
		return this._price;
	}
	set
	{
		if (_price == value)
			return;
		decimal oldPrice = _price;
		_price = value;
		OnPriceChanged(new PriceChangedEventArgs(oldPrice, _price));
	}
}

Triển khai hàm main

class Program
{
	static void Main(string[] args)
	{
		Product product = new Product();
		product.Price = 10000;
		product.PriceChanged += product_PriceChanged;
		product.Price = 50000;
		Console.ReadLine();
	}

	static void product_PriceChanged(object sender, PriceChangedEventArgs e)
	{
		Console.WriteLine("Old Price: {0}", e.OldPrice);
		Console.WriteLine("New Price: {0}", e.NewPrice);
	}
}

Phương thức xử lý sự kiện:

void product_PriceChanged(object sender, PriceChangedEventArgs e)

Có điểm tương đồng với phương thức xử lý sự kiện click của Button hay TextChanged của TextBlock

Ngoài ra có thể ép kiểu sender về Product

static void product_PriceChanged(object sender, PriceChangedEventArgs e)
{
	Product p = sender as Product;
	Console.WriteLine("Price: {0}", p.Price);
	Console.WriteLine("Old Price: {0}", e.OldPrice);
	Console.WriteLine("New Price: {0}", e.NewPrice);
}

Lưu ý

Với những quy tắc đặt ra như vậy, việc tuân thủ hay không là tùy theo mỗi lập trình viên, ví dụ class Product không cần thiết phải viết thêm phương thức OnPriceChanged mà có thể triển khai trực tiếp như sau:

public decimal Price
{
	get
	{
		return this._price;
	}
	set
	{
		if (_price == value)
			return;
		decimal oldPrice = _price;
		_price = value;
		if (PriceChanged != null)
			PriceChanged(this, new PriceChangedEventArgs(oldPrice, _price));
	}
}

Download demo

Demo_Event_VS2019.zip

IO Stream

IO Stream Co., Ltd

30 Trinh Dinh Thao, Hoa Thanh ward, Tan Phu district, Ho Chi Minh city, Vietnam
+84 28 22 00 11 12
developer@iostream.co

383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024