CSharp - Standard Event Pattern

Introduction

C# defines a standard pattern for writing events.

System.EventArgs is a predefined class which is a base class for transferring data for an event.

The following code subclass EventArgs to transfer the old and new value for a ValueChanged event.

public class ValueChangedEventArgs : System.EventArgs
{
       public readonly decimal OldValue;
       public readonly decimal NewValue;

       public ValueChangedEventArgs (decimal oldValue, decimal newValue)
       {
         OldValue = oldValue;
         NewValue = newValue;
       }
}

The EventArgs subclass typically exposes data as properties or as read-only fields.

Event Delegate

The event delegate must have a void return type.

It must accept two arguments: the first of type object, and the second a subclass of EventArgs.

The first argument indicates the event broadcaster.

The second argument contains the information to transfer.

The event delegate's name must end with EventHandler.

We can use the generic delegate called System.EventHandler<> from C#.

public delegate void 
       EventHandler<TEventArgs>(object source, 
                                TEventArgs e) 
                                where TEventArgs : EventArgs;

Here's the complete example:

Demo

using System;

public class ValueChangedEventArgs : EventArgs
{
       public readonly decimal OldValue;
       public readonly decimal NewValue;

       public ValueChangedEventArgs (decimal oldValue, decimal newValue)
       {//  ww  w  .  j a va2 s  .  co  m
         OldValue = oldValue; NewValue = newValue;
       }
}

public class ProgressBar
{
       string symbol;
       decimal myCurrentValue;

       public ProgressBar (string symbol) {this.symbol = symbol;}

       public event EventHandler<ValueChangedEventArgs> ValueChanged;

       protected virtual void OnValueChanged (ValueChangedEventArgs e)
       {
         ValueChanged?.Invoke (this, e);
       }

       public decimal Value
       {
         get { return myCurrentValue; }
         set
         {
           if (myCurrentValue == value)
               return;
           decimal oldValue = myCurrentValue;
           myCurrentValue = value;
           OnValueChanged (new ValueChangedEventArgs (oldValue, myCurrentValue));
         }
       }
}

class Test
{
       static void Main()
       {
         ProgressBar myProgressBar = new ProgressBar ("THPW");
         myProgressBar.Value = 27.10M;
         // Register with the ValueChanged event
         myProgressBar.ValueChanged += myProgressBar_ValueChanged;
         myProgressBar.Value = 31.59M;
       }

       static void myProgressBar_ValueChanged (object sender, ValueChangedEventArgs e)
       {
         if ((e.NewValue - e.OldValue) / e.OldValue > 0.1M)
           Console.WriteLine ("Alert, 10% myProgressBar myCurrentValue increase!");
       }
}

Result