C# WPFでカスタムイベントを作成する方法!初心者向けチュートリアル
生徒
「C#とWPFを使ってアプリを作っていますが、自分で独自のイベントを作る方法がわかりません。」
先生
「WPFでは、独自のタイミングで処理を呼び出すカスタムイベントという仕組みを作ることができます。」
生徒
「どうやって自分でイベントを定義して、それを他の場所から呼び出すのですか?」
先生
「まずはカスタムイベントの基本的な仕組みと作り方を順を追って解説しますね。」
1. カスタムイベントとは何か?
プログラミングにおけるイベントとは、何らかの出来事を指します。例えば、ボタンをクリックする、マウスを移動させる、キーボードを押すといった動作がイベントです。C#のWPFアプリケーション開発において、標準で用意されているボタンクリックなどのイベントだけでなく、プログラマーが自分の好きなタイミングで発生させることができるものをカスタムイベントと呼びます。
例えば、データが読み込まれたタイミングや、特定の計算が終わったタイミングで、他の画面やクラスに「準備完了!」という合図を送りたい場合に非常に便利です。これを理解することで、画面同士の連携がスムーズになり、より高度なアプリケーション開発が可能になります。
2. イベントを定義する準備
カスタムイベントを作成するには、まずそのイベントが「何の情報を持つか」を定義する必要があります。イベントが発生したときに、特別なデータ(例えば「処理完了時刻」など)を渡したい場合は、EventArgsクラスというものを継承した独自のクラスを作成します。もし、単に「起きたこと」だけを伝えたい場合は、標準のEventArgsをそのまま使うことができます。
ここでは、最もシンプルに「イベントが発生した」ことだけを伝える方法を見ていきましょう。WPFのプロジェクト内で、イベントを送信するクラスの中にイベントの定義を書きます。
public class MyDataSender
{
// イベントの定義
public event EventHandler MyCustomEvent;
public void DoWork()
{
// ここで処理を行う
// 処理が終わったらイベントを発生させる
MyCustomEvent?.Invoke(this, EventArgs.Empty);
}
}
3. EventHandlerの役割を解説
先ほどのコードに出てきたEventHandlerは、イベントを処理するための「窓口」となる型(型とはデータの種類のこと)です。WPFを含むC#では、イベントは基本的にこのEventHandlerを使って定義します。
?.Invoke(this, EventArgs.Empty)という部分は少し難しく見えるかもしれませんが、これは「もしイベントを待ち受けている人がいれば、その人たちに『イベントが発生しましたよ』と合図を送る」という命令です。thisは自分自身(送信元)を指し、EventArgs.Emptyは特別なデータは送らないということを意味しています。
4. イベントを待ち受ける方法
イベントを定義したら、次はそれを受け取る側(受信側)の処理が必要です。イベントを受け取るには、+=という記号を使って、イベントが発生したときに実行したいメソッドを登録します。これをイベントハンドラーの登録と呼びます。
例えば、MainWindow(メインの画面)でイベントを受け取るコードは以下のようになります。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyDataSender sender = new MyDataSender();
// イベントハンドラーの登録
sender.MyCustomEvent += OnMyCustomEventReceived;
sender.DoWork();
}
private void OnMyCustomEventReceived(object sender, EventArgs e)
{
MessageBox.Show("カスタムイベントを受け取りました!");
}
}
5. イベントに独自のデータを渡す方法
もし、単にイベントが起きたことを伝えるだけでなく、具体的な「名前」や「数値」といったデータをイベントの相手に渡したい場合はどうすればよいでしょうか。そのためには、EventArgsを拡張したクラスを作ります。
public class MyEventArgs : EventArgs
{
public string Message { get; set; }
}
public class DataProvider
{
public event EventHandler<MyEventArgs> DataLoaded;
public void LoadData()
{
// データを読み込んだ後にイベントを発行
DataLoaded?.Invoke(this, new MyEventArgs { Message = "読み込み成功!" });
}
}
このようにEventHandler<T>を使うと、定義したMyEventArgsを通じて、受信側にデータを送ることが可能になります。これにより、アプリケーション内での情報共有が飛躍的に簡単になります。
6. 注意すべきメモリリークの対策
最後に、少しだけ大切な注意点があります。イベントにメソッドを登録(+=)したままにすると、登録された側のオブジェクトがメモリから削除されず、結果としてメモリリーク(メモリが解放されずに残り続ける現象)を引き起こすことがあります。これを防ぐために、役割が終わったときは-=を使って登録を解除するのが良い習慣です。
// イベントの登録解除
sender.MyCustomEvent -= OnMyCustomEventReceived;
WPFでの開発において、この「登録したら解除する」というルールを守るだけで、アプリケーションの動作が安定し、クラッシュしにくいプログラムを作ることができます。カスタムイベントは強力な道具ですので、ぜひ使いこなしてみてください。