0x52——C#中自定义Event与Handler

最初学会自定义Event和Handler是通过这篇博客:Simple custom event handling。另外我也看过:Writing C# Custom Events,不过没太看懂那篇在讲什么,可能是因为没有细看。

C#中的Event模型是基于发布者(Publisher)与订阅者(Subscriber)(注:应该是在讲Observer Pattern)。每一个发布者可以拥有多个时间,每一个事件又可以有多个订阅者。Publisher在满足一定条件之后,会发布一个Event给所有的订阅者。订阅者则会做出相应的反应。在C#中,任意一个控件都可以发布event,其他的任何控件也都可以订阅此event,并针对此做出相应的反应。

 

惯例

在处理Event时,有如下的惯例:

1. .net framework中的Event Handlers返回值为空,且需要传两个参数;

2. 第一个参数是事件源(即发布者);

3. 第二个参数是一个EventArgs的衍生类;

4. Event是发布它的类的性质(Properties);

5. Event的Keyword控制该Event如何被订阅的类获得。

 

例子

我们有一个产品,它有一个Name的Property,当它的名字发生变化时,我们希望一个Label中的内容也发生相应的变化。于是就需要Product是一个Publisher,而Label就是一个订阅者。

注:我这里的代码是考的样例代码,实际上其中并没有使用什么Label,而只是直接修改了一次。但我觉得基本是讲清楚了Event的定制方法。更详细地也可以参加原文。

首先我们先定义Event,以及会触发此Event的Method。

public class Product
{
  public string Name { get; set; }
  // Delegate
  public delegate void PropertyChangeHandler (object sender,  EventArgs data);
  // The event
  public event PropertyChangeHandler PropertyChange;
  // The method which fires the Event
  protected void OnPropertyChange (object sender,  EventArgs data)
  {
    // Check if there are any Subscribers
    if (PropertyChange!= null)
    {
      // Call the Event
      PropertyChange (this, data);
    }
  }
}

这里我们定义一个delegate,叫做PropertyChangeHandler,这个delegate需要被所有的订阅者执行。

 

之后我们就需要定义一个Event,它是EventArgs的衍生类。

public class PropertyChangeEventArgs : EventArgs
{
  public string PropertyName { get; internal set; }
  public object OldValue { get; internal set; }
  public object NewValue { get; internal set; }
  public PropertyChangeEventArgs(string propertyName, object oldValue, object newValue)
  {
    this.PropertyName = propertyName;
    this.OldValue = oldValue;
    this.NewValue = newValue;
  }
}

public class Product
{
  private string name;
  public string Name {
    get
    {
      this.name;
    }
    set
    {
      Object old = this.name;
      this.name = value;
      OnPropertyChange(this, new PropertyChangeEventArgs(“Name”, old, value));
    }
  }

  // Delegate
  public delegate void PropertyChangeHandler (object sender,  PropertyChangeEventArgs data);
  // The event
  public event PropertyChangeHandler PropertyChange;
  // The method which fires the Event
  protected void OnPropertyChange (object sender,  PropertyChangeEventArgs data)
  {
    // Check if there are any Subscribers
    if (PropertyChange!= null)
    {
      // Call the Event
      PropertyChange (this, data);
    }
  }
}

注:从后文看,Event中的PropertyName只是一个调用事件的条件项,实际上并不是主要的。也可以通过满足其它条件时触发此事件,甚至可以任何时候都触发此事件。

然后我们定义一个Product并订阅此事件。

private static Product Product;
static void Main(string[] args)
{
    Program.Product = new Product();
//订阅 Program.Product.PropertyChange
+= new Product.PropertyChangeHandler(Program.PropertyHasChanged); Program.Product.Name = "new"; Program.Product.Name = "value changed again"; Console.ReadLine(); } public static void PropertyHasChanged(object sender, PropertyChangeEventArgs data) { if (data.PropertyName == "Name") { Console.WriteLine("New value: '" + (string)data.NewValue + "' was: '" + (string)data.OldValue + "'"); } }

在Name改变的时候,OnPropertyChange就会raise event。然后所有的订阅者都会调用相应的函数。

posted @ 2012-04-19 22:22  cuero  阅读(820)  评论(0编辑  收藏  举报