Press "Enter" to skip to content

Simple custom C# event handler

The event model in C# is based on idea of publisher and subscribers. Each publisher can have more subscribers subscribed to each event. Publisher will do some logic and publish an event to all subscribers. Subscribers will do their logic reacting to raised event. In C#, any object can publish a set of events to which other applications can subscribe. When the publishing class raises an event, all the subscribed applications are notified. Example of this behaviour can be that the application will subscribe to event which will be raised from database connection control when the connection is lost. Main application will know, that this happened and can react on that event ?reconnect, show alert message, etc.

Conventions

The following important conventions are used with events:

  • Event Handlers in the .NET Framework return void and take two parameters.
  • The first paramter is the source of the event; that is the publishing object.
  • The second parameter is an object derived from EventArgs.
  • Events are properties of the class publishing the event.
  • The keyword event controls how the event property is accessed by the subscribing classes.

Example

Lets say that we have Product class which has Name property. When the name is changed we want ot change this name in Label as well. We don?t know from where this name can be changed. We will ?convert? product class into event publisher and the window where is the label will subscribe to this event.

First step will be to create the event and method which will fire this event.

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);
    }
  }
}

We created delegate which encapsulates any method that takes these attributes, this delegate must be implemented by all subscribers. Now we need one small change to the class. That will be to fire the event, when Name property is changed. It can be nice to pass information about this change to subscribers with what have been changed and to have old value and new value. For this we will create PropertyChangeEventArgs class which will be derived from 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
    {
      // Raise the event only when the property was really changed (thx Kimleng)
      if(this.Name != value)
      {
        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);
    }
  }
}

Now we are done with the Product class (publisher) and can subscribe to the OnPropertyChange event.

protected void Page_Init(object sender, EventArgs e)
{
  this.Product = new Product();
  this.Product.OnPropertyChange += new Product.PropertyChangeHandler(PropertyHasChanged);
}
protected void Page_Load (object sender, EventArgs e)
{
  this.Product.Name = "New name";
}

public void PropertyHasChanged (object sender,  PropertyChangeEventArgs data)
{
  if(data.PropertyName == ?Name?)
  {
    this.ProductLabel.Text = (string)data.NewValue + " was " + (string)data.OldValue;
  }
}

In the Init event we created product instance and subscribe to OnPropertyChange event of Product class. In Load phase we changed name of that product. This operation fired PropertyChange and this was send to all subscribers. This calls PropertyHasChanged method with all informations.

Donwload example: Download

25 Comments

  1. Pawan Rai
    Pawan Rai April 3, 2009

    It is really a best article to understand about events

  2. Ariz
    Ariz February 23, 2010

    hey Martin,
    thanks mate for a wonderful article.

  3. Jirka
    Jirka March 23, 2010

    Hi,
    I have small problem with this code in VS2005. I changed the default get & set to VS2005 style. Problem is, that I get always error “” on line this.Product. OnPropertyChange += Product.PropertyChangeHandler(PropertyHasChanged); .The error is: “…Product.PropertyChangeHandler’ is a ‘type’, which is not valid in the given context”

    any idea? thx a lot!

  4. Peter
    Peter April 7, 2010

    Best example for property change event I found! Thanks a lot!

  5. Rash
    Rash April 15, 2010

    Hi Martin,
    Thanks a lot….
    This is the best example i found and understood event handling very easily.

  6. Shweta
    Shweta May 18, 2011

    Really very helpful example for custom Event handling. Thanks.
    It would be better if you also specify how to subcribe an event for more than 1 subscribers.?

  7. Almo
    Almo August 22, 2011

    Great tutorial. Though I was confused by the

    this.Product.OnPropertyChange +=

    typo.

  8. Salih Ya
    Salih Ya December 3, 2011

    I have been searching a simple events example for a day now. Thanks to you, i have finally understood to register the event of dll.

    There is a communication library dll i am preparing. And when a message comes, dll fires the event. So the client does not worry about connection, etc, it only subscribes to event and does proper jobs if a message is received.

    In order to achieve this, i have searched a lot of resources, but nobody tells how to do it properly.

    Your source code solved my problem. Thank you very much.

  9. Dimi
    Dimi December 6, 2011

    Thanks a lot bro!

  10. diegospc
    diegospc May 19, 2012

    The Page_Init method has an error:
    this.Product.OnPropertyChange += new Product.PropertyChangeHandler(PropertyHasChanged);
    must be:
    this.Product.PropertyChange += new Product.PropertyChangeHandler(PropertyHasChanged);

    • Amy
      Amy September 6, 2014

      It could be:
      Program.Product.PropertyChange += Program.PropertyHasChanged;

  11. Luis Ladino
    Luis Ladino May 23, 2012

    Thanks a lot for this brief and clear expanation about Events.

  12. Kiran
    Kiran May 28, 2012

    Awesome article. Neatly explained. Thanks to you.

  13. Joakim
    Joakim May 28, 2012

    Thank you! This way really helpful

  14. Kimleng
    Kimleng June 11, 2012

    I think this should be add for validating data is if value is the same.
    public string Name {
    get
    {
    this.name;
    }
    set
    {
    if(this.Name !=value)
    {
    object old = this.name;
    this.name = value;
    OnPropertyChange(this, new PropertyChangeEventArgs(?Name?, old, value));
    }
    }
    }

  15. Josh
    Josh June 21, 2012

    Fantastic article. As a novice, self-learning programmer, it’s really hard to find articles about some of these advanced concepts in a way that programmers, such as my self, can both understand and see the benefits.

  16. Martin M?lek
    Martin M?lek July 2, 2012

    @Kimleng
    You are right. It will be better and the event should be raised only when the property is changed. But for the example is not so important. I’ll update the post.

  17. GTank1
    GTank1 October 3, 2012

    Amazing article explaining events in an easy to understand way. Thanks for taking the time to write such a well thought out article.

  18. Halivudestevez
    Halivudestevez October 18, 2012

    All the c# event tutorial begins with delegate.
    Delegate is not simple to understand, that should be the second step in a tutorial. Understanding “public event EventHandler” should be the first.

  19. mangesh
    mangesh November 20, 2012

    Thanks for explaining this concept in such a simpler way.

  20. souldeep
    souldeep January 10, 2013

    Thank you so much for this wonderful example. I have spend a lot of time trying to understand how all these pieces work together. This is by far the best simple example I have found.

  21. Eddy
    Eddy July 9, 2013

    Very helpful example. Simple and clear but ideally to understand events and delegates.
    Many thanks.

  22. Francisco Araújo
    Francisco Araújo August 9, 2016

    The best article about…!!!

    Thanks Martin Malek!!

  23. Francisco Araújo
    Francisco Araújo August 10, 2016

    // This code was adaptade for Windows Forms Application
    // of the original code of the Martin Malek
    // Thank´s Martin Malek!
    // Your application is the best.., high level!

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    namespace APP16
    {

    public partial class Form1 : Form
    {

    public Form1()
    {
    InitializeComponent();
    }

    public Product Prod;

    private void button1_Click(object sender, EventArgs e)
    {
    Prod = new Product();
    Prod.PropertyChange += new Product.PropertyChangeHandler(PropertyHasChanged);
    Prod.Name = “new”;
    Prod.Name = “value changed again”;
    }

    public static void PropertyHasChanged(object sender, PropertyChangeEventArgs data)
    {
    if (data.PropertyName == “Name”)
    {
    MessageBox.Show(“New value: ‘” + (string)data.NewValue + “‘ was: ‘” + (string)data.OldValue + “‘”, “Atenção”, MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
    }
    }

    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
    {
    return 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
    public void OnPropertyChange(object sender, PropertyChangeEventArgs data)
    {
    // Check if there are any Subscribers
    if (PropertyChange != null)
    {
    // Call the Event
    PropertyChange(this, data);
    }
    }
    }
    }
    }

Leave a Reply to Joakim Cancel reply

Your email address will not be published. Required fields are marked *