Lesson 1: A simple event
The ability to fire an event is core to most Windows development projects. Events are useful for updating a user interface with changed data, or causing a piece of code to run after another piece of code has completed. .NET has brought us a powerful model for programming events. In this lesson we will write a small application that will show an example of an event.This sample illustrates the use of an event in its simplest form.
First, we will start by creating a small class that will fire an event when a file is created or deleted.Our class will be named FileWatch and will fire an event named OnFileChange.This class will check for the existence of a file named test.txt that exists in the directory that contains the executing application (current directory). If the existence of the file changes we will fire off the OnFileChange event.This also contains a method named MonitorFile that will continually look for the file.
When creating a class that has a consumable event, you must first declare a delegate (outside the context of the class).
public
delegate void FileWatchEventHandler(object sender, EventArgs e);
Next, we will create the actual FileWatch class.The first thing we do in our class is declare the public event which we will be raising in the MonitorFile method.You will note that the event type is the name of the delegate that we defined earlier.
public
event FileWatchEventHandler FileWatchEvent;
Now we need to create a method that we can call which will actually raise our event. So, any time that we wish to raise our FileWatchEvent, we simply call our OnFileChange method. When you raise an event in .NET you can pass data to the event consumer (the code that is reacting to the event). In this example we are not going to pass any data back to the consumer however we still need to pass back an EventArgs object back, the object we send back will be empty.
protected virtual void OnFileChange(EventArgs e)
{
if (FileWatchEvent != null)
{
// Invokes the delegates.
FileWatchEvent(this, e);
}
}
The last thing we need to do in our FileWatch class is to create a method that will perform a bit of work and raise our event at the appropriate time.The MonitorFile method will constantly check the current directory for the file named test.txt.If the existence of this file changes (IE: the file gets created or deleted) then we raise our event by calling the method OnFileChange.
public void MonitorFile()
{
bool bCurrentStatus;
while(true)
{
bCurrentStatus = File.Exists("test.txt");
if ( bCurrentStatus != _bLastStatus )
{
_bLastStatus = bCurrentStatus;
OnFileChange( EventArgs.Empty );
}
//Sleep for a little
Thread.Sleep(250);
}
}
Please refer to our completed code below in figure 1.
Figure 1
/* Example 1: Fire a simple event, do not pass values to the event consumer. */
using System;
using System.Threading; // For the sleep functionality.
using System.IO; // For the File class.
namespace Sample.Event
{
public delegate void FileWatchEventHandler(object sender, EventArgs e);
public class FileWatch
{
private bool _bLastStatus = false;
public FileWatch()
{
//
// TODO: Add constructor logic here
//
}
public event FileWatchEventHandler FileWatchEvent;
protected virtual void OnFileChange(EventArgs e)
{
if (FileWatchEvent != null)
{
// Invokes the delegates.
FileWatchEvent(this, e);
}
}
public void MonitorFile()
{
bool bCurrentStatus;
while(true)
{
bCurrentStatus = File.Exists("test.txt");
if ( bCurrentStatus != _bLastStatus )
{
_bLastStatus = bCurrentStatus;
OnFileChange( EventArgs.Empty );
}
//Sleep for a little
Thread.Sleep(250);
}
}
}
}
In the next section we will consume our event. In order to do this, we will create a small windows application to start our file monitor and react to the event. For simplicity we will simply indicate that something has changed. In the sample I invoke the MonitorFile method in its own thread. This was done so that the file can be monitored without blocking the forms UI from being updated.
We compile the FileWatch class and begin writing a windows form application.Add a reference to the FileWatch.dll and import the namespace by using the following code:
using Sample.Event;
Inside the windows form class we add a reference to the FileWatch class.We will use this reference to wire up the event to a method in the windows form class. This local method will update the form when the event is raised.
public class frmMain : System.Windows.Forms.Form
{
private Sample.Event.FileWatch FileWatchEventSource;
Next we will wire up the event to a local method in the frmMain class.We wire up
he event by using the following code in the class constructor:
public frmMain()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Create an instance of the FileWatch class so we can consume it's event.
FileWatchEventSource = new Sample.Event.FileWatch();
// "Wire up" the FileWatch event so we can respond to it if it should fire.
We wire up the FileWatchEvent to the local method named OnFileChange with the following line of code:
FileWatchEventSource.FileWatchEvent +=
new Sample.Event.FileWatchEventHandler( OnFileChange );
Once you wire up the event to a method that will handle the event, you need to run the code that will start the MonitorFile method in the FileWatch class. In this sample I decided to start the MonitorFile method in its own thread.I did this so that while the MonitorFile method is running the form can sit idle until the event we created is raised. See the code section below, it spawns the MonitorFile method in a new thread.
//Make a thread to run the monitor method.
thrd = new Thread(new ThreadStart(FileWatchEventSource.MonitorFile));
//Start the thread.
thrd.Start();
The only thing left to do now is to actually react to the event when it is raised.In order to do this we need to write a method that will handle the event in the windows form class.We already wired up the FileWatchEvent to a local method named OnFileChange,so lets create that method so we can use the event.
Place a listbox control on the form and name it listBox.When the event is raised, we will add a line to the listbox indicating that the file has changed.
private
void OnFileChange( object Sender, EventArgs e )
{
// e will be empty in this sample because we are not passing args.
listBox.Items.Add( DateTime.Now.ToString() + ": file changed." );
}
When you consume an event, the EventHandler will pass a reference to the sender and an EventArgs class.The EventArgs class is used to pass information from the event source to the event consumer.In this sample, we are not passing any information to the event consumer and will not use the EventArgs class in this method.Instead, we will simply react to the event by inserting a line of text into a listbox.