【WinForm】イベントを使ったフォーム間通信
複数のフォームを使ったアプリで、サブ画面の更新をきっかけにメインの画面(クラス)で登録されているメソッドが実行される方法についてみていきましょう
サンプルの構成(データを渡さなくても良い場合)
このサンプルコードは、Windows Forms アプリケーションで使用されるイベント駆動型プログラミングの一例を示しています。具体的には、メインフォーム (Form1
) とサブフォーム (SubForm
) 間でのイベント通信の実装方法を示しています。以下、デザイン画面とコードの主要な部分について説明します。
Form1
デザイン画面
Form1
クラス
Form1
はメインフォームを表し、Form
クラスから派生しています。- コンストラクタ (
public Form1()
) 内で、InitializeComponent()
メソッドを呼び出してフォームの初期化を行っています。これはデザイナーによって生成されたコードで、フォーム上のコントロールの配置やプロパティの設定を含みます。 - その後、
SubForm
インスタンスを作成し、SubForm
から発行されるOnButtonClicked
イベントにCheckSubForm
メソッドをイベントハンドラとして登録しています。これにより、サブフォーム上の特定のボタンがクリックされたときにCheckSubForm
メソッドが呼び出されるように設定されています。 CheckSubForm
メソッドでは、メインフォーム上のラベル (label1
) のテキストを変更して、サブフォームのボタンが押されたことを示しています。
// メインフォームのクラス定義
public partial class Form1 : Form
{
// Form1のコンストラクタ
public Form1()
{
InitializeComponent(); // フォームの初期設定を行うメソッド
// サブフォームのインスタンスを作成
SubForm subForm = new SubForm();
// サブフォームのボタンクリックイベントにイベントハンドラを登録
subForm.OnButtonClicked += CheckSubForm;
// サブフォームを表示
subForm.Show();
}
// サブフォームのボタンがクリックされた時に呼び出されるメソッド
public void CheckSubForm()
{
// メインフォーム上のラベルのテキストを変更
label1.Text = "サブフォームのボタンが押された";
}
}
SubForm
デザイン画面
button1コントロールのイベントハンドラの登録
SubForm
クラス
SubForm
はサブフォームを表し、同様にForm
クラスから派生しています。- このクラスでは、
OnButtonClicked
というAction
型のイベントを公開しています。これは、サブフォーム上の特定のボタンがクリックされたことを外部に通知するためのイベントです。 - イベントハンドラ
OnSubFormButtonClicked
は、サブフォーム上のボタンがクリックされたときに呼び出されるメソッドです。このメソッド内で、OnButtonClicked
イベントが null でないかをチェックし(null 条件演算子?.
を使用)、null でない場合にイベントを発火 (Invoke()
) しています。これにより、イベントに登録されたすべてのハンドラ(この場合はForm1
のCheckSubForm
メソッド)が呼び出されます。
// サブフォームのクラス定義
public partial class SubForm : Form
{
// サブフォームのボタンクリックイベントを外部に公開するイベントデリゲート
public event Action OnButtonClicked;
// SubFormのコンストラクタ
public SubForm()
{
InitializeComponent(); // フォームの初期設定を行うメソッド
}
// サブフォームのボタンがクリックされた時に呼び出されるイベントハンドラ
private void OnSubFormButtonClicked(object sender, EventArgs e)
{
// イベントがnullでないかチェックしてからイベントを発生
OnButtonClicked?.Invoke();
}
}
実行結果
- アプリケーションが開始され、
Form1
のインスタンスが作成されます。 Form1
のコンストラクタが呼ばれ、InitializeComponent()
が実行されます。これにより、フォーム上のコントロール(例えばlabel1
など)が配置されます。- コンストラクタ内で
SubForm
のインスタンスが生成され、OnButtonClicked
イベントにCheckSubForm
メソッドがイベントハンドラとして関連付けられます。 SubForm
が表示されます。- ユーザーが
SubForm
上のボタン(おそらくbutton1
と名付けられたボタン)をクリックします。 - ボタンのクリックイベントが
OnSubFormButtonClicked
メソッドをトリガーし、そのメソッド内でOnButtonClicked
イベントが発火します(。 OnButtonClicked
イベントの発火により、Form1
のCheckSubForm
メソッドが呼び出されます。CheckSubForm
メソッドによって、Form1
上のlabel1
のテキストが「サブフォームのボタンが押された」という文字列に変更されます。
実行結果として、ユーザーが SubForm
のボタンをクリックすると、Form1
上の label1
が新しいテキストで更新され、ユーザーにアクションが行われたことが視覚的にフィードバックされることになります。
サンプルの構成(データを渡したい場合)
このサンプルは、Windows Forms アプリケーションでカスタムイベント引数を持つイベントの使用方法を示すものです。Form1
クラスと SubForm
クラス、およびカスタムイベント引数を定義する MyEventArgs
クラスで構成されています。
Form1
デザイン画面
Form1
クラス
Form1
はSystem.Windows.Forms.Form
クラスを継承しています。これは、Windows Forms アプリケーションでウィンドウ(フォーム)を作成するための基本クラスです。- コンストラクタ
public Form1()
は、フォームがインスタンス化されたときに呼ばれます。 - コンストラクタ内で
InitializeComponent()
メソッドが呼ばれることにより、フォーム上のコントロール(この場合はおそらくlabel1
)の初期設定が行われます。 - 新たに
SubForm
インスタンスが作成され、subForm.OnButtonClicked
というイベントにCheckSubForm
メソッドがイベントハンドラとして登録されます。これにより、サブフォームで定義されたイベントが発生した際に、Form1
のCheckSubForm
メソッドが呼び出されるようになります。 subForm.Show();
により、サブフォームが表示されます。CheckSubForm
メソッドは、SubForm
からのイベントを受け取り、label1
のテキストを更新します。ここでイベントの引数としてMyEventArgs
クラスのインスタンスが渡され、そのHp
プロパティの値をラベルに表示します。
using System.Windows.Forms;
namespace FormComSample
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SubForm subForm = new SubForm();
subForm.OnButtonClicked += CheckSubForm;
subForm.Show();
}
private void CheckSubForm(object sender, MyEventArgs e)
{
label1.Text = $"サブフォームのボタンが押された {e.Hp}";
}
}
}
SubForm
デザイン画面
このサンプルでは、button1コントロールのイベントハンドラの登録はコードで実現していますので不要です
SubForm
クラスと MyEventArgs
クラス
SubForm
もまたForm
クラスを継承しています。SubForm
にはEventHandler<MyEventArgs>
デリゲートを使ったOnButtonClicked
というイベントが定義されています。このイベントはSubForm
のボタンがクリックされた時に発生します。button1.Click
イベントハンドラは匿名メソッドを使用しており、ボタンがクリックされるとMyEventArgs
インスタンスを新規作成し、Hp
プロパティに100
を設定してからOnButtonClicked
イベントを発火させます。MyEventArgs
はEventArgs
クラスから派生していて、Hp
という追加の情報をイベントと共に送ることができます。
このコードの全体的な流れは、Form1
が起動するとすぐに SubForm
を表示し、サブフォーム上のボタンがクリックされたときにメインフォームの label1
を更新して、「サブフォームのボタンが押された」と表示するとともに、Hp
の値を表示するというものです。
using System;
using System.Windows.Forms;
namespace FormComSample
{
public partial class SubForm : Form
{
public event EventHandler<MyEventArgs> OnButtonClicked;
public SubForm()
{
InitializeComponent();
button1.Click += (s, e) =>
{
MyEventArgs args = new MyEventArgs();
args.Hp = 100;
// nullチェックを追加
OnButtonClicked?.Invoke(this, args);
};
}
}
public class MyEventArgs : EventArgs
{
public int Hp;
}
}
実行結果
- アプリケーションが起動され、
Form1
のインスタンスが作成されます。 Form1
のコンストラクタが実行され、InitializeComponent
メソッドを通じてフォーム上のコントロールが初期化されます。SubForm
の新しいインスタンスが作成され、OnButtonClicked
イベントに対してCheckSubForm
メソッドがイベントハンドラとして登録されます。subForm.Show()
が呼び出され、サブフォームが表示されます。- ユーザーが
SubForm
上のbutton1
をクリックすると、button1.Click
イベントに関連付けられた匿名メソッドが実行されます。 - 匿名メソッド内で
MyEventArgs
インスタンスが生成され、Hp
プロパティに100
が設定されます。 OnButtonClicked
イベントが発火され、Form1
のCheckSubForm
メソッドがコールバックとして呼び出されます。CheckSubForm
メソッドがlabel1
のテキストを更新し、サブフォームのボタンが押されたことと、Hp
の値(この例では100
)が表示されます。
結果として、Form1
上の label1
には "サブフォームのボタンが押された 100"
というテキストが表示されることになります。これにより、サブフォームでのユーザーのアクションがメインフォームに伝えられ、その結果がメインフォーム上でユーザーにフィードバックされます。
ディスカッション
コメント一覧
まだ、コメントがありません