Programming in C#
EventsEvents
CSE 494R
(proposed course for 459 Programming in C#)
Prof. Roger Crawfis
The event field
An event field is just a special delegate
instance.
Usually exposed as a public field (acts
more like a property).
Restricts the delegate operations (to the
public) to += and -=.
Only the class (or its decendents) can fire the
event.
Only the class (or its descendents) can clear or
reset the values (using =).
Published Properties
public class SharedFloat
{
public delegate void NewValue(float value);
public event NewValue ValueChanging;
public event NewValue ValueChanged;
private void Dummy(float value) {}
public SharedFloat()
{
// This avoids the check for null.
ValueChanging += Dummy;
ValueChanged += Dummy;
}
}
private float myFloat;
public float Value
{
get { return myFloat; }
set
{
ValueChanging(value);
myFloat = value;
ValueChanged(myFloat);
}
}
Example
class Model {
public event Notifier notifyViews;
public void Change() { ... notifyViews("Model"); }
}
class View {
public View(Model m) { m.notifyViews += new Notifier(Update); }
void Update(string sender) { Console.WriteLine(sender + " was changed"); }
}
class Test {
static void Main() {
Model model = new Model();
new View(model); new View(model); ...
model.Change();
}
}
Event Accessors
Event subscription can be controlled/monitored within
a class.
Similar to properties – add accessor is called during
+=, remove accessor is called during -=
Both accessors need to be declared.
public delegate void MyDelegate ();
class A {
private MyDelegate m_DelegateBehind;
public event MyDelegate Event {
add { m_DelegateBehind += value; }
remove { m_DelegateBehind -= value; }
}
…
}
Classes with events
A class instance may publish several events.
Each event member holds a collection of
subscribers.
As with delegates, the publishing object calls
each registered listener in turn.
.
Naming Conventions in .NET
The name of an event ends with ing if the
notification occurs before the state change or
actual event.
The name of an event ends with ed if the
notification occurs after the state change or
actual event.
Some typical event names
form.Closing // has not closed yet, this can abort the close
form.Closed // by this time the form is closed.
msg.Sending // suggests you can intercept and modify
// the message just before sending
msg.Sent // telling you that it has already gone.
What does this buy us?
Flexible, loose coupling
Very clean separation of concerns
Easily extensible: we can add new
observers without having to modify the
publisher.
Modules can be “wired” to listen to one
another as part of the startup logic,
The only type coupling between the
modules is determined by the type of the
event delegate.
Examples in .NET Framework
A Timer has a Tick event that you subscribe
to. You can set the Interval between ticks.
The EventLog component allows you to listen
to EventWritten, which will alert you every time
anything is written to your machine’s event log.
The FileSystemWatcher component watches a
directory structure. It uses a filter (e.g., “*.xml”)
and exposes several events:
Changed
Created
Renamed
Deleted
The Event Pattern in .NET
Delegates for event handling in .NET have the following
signature:
delegate void SomeEvent (object sender, MyEventArgs e);
The return type is void.
The first parameter is a reference to the class that contains
the event (the publisher).
The second parameter is used to pass (push) data to the
subscribers. It’s type is derived from System.EventArgs.
Using this pattern, I can use a method like the following for
all .NET events (using contra-variance):
private void MyEventHandler( object sender, EventArgs e) {
// log the event
…
}
This method takes any object as the first
parameter and any object derived from
EventsArgs as the second.
Example
public delegate void KeyEventHandler (object sender, KeyEventArgs e);
public class KeyEventArgs : EventArgs
{
public virtual bool Alt { get {...} } // true if Alt key was pressed
public virtual bool Shift { get {...} } // true if Shift key was pressed
public bool Control { get {...} } // true if Ctrl key was pressed
public bool Handled { get{...} set {...} } // indicates if event was already handled
public int KeyValue { get {...} } // the typed keyboard code
...
}
class MyKeyListener
{
public MyKeyListener(...) { keySource.KeyDown += new
KeyEventHandler(HandleKey);}
void HandleKey (object sender, KeyEventArgs e) {...}
}
Programming in C#
EventsEvents
CSE 494R
(proposed course for 459 Programming in C#)
Prof. Roger Crawfis