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)
và
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 get
, set
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.
- Tham số thứ nhất có kiểu là
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)); } }