Winフォームアプリで、イベントを学びましょう(基本)

2022年7月25日

イベントの学習は難易度が高いですね
教科書、入門書でも扱ってないものが多いです。また、WinフォームアプリをVisualStudioで作る場合、例えば、ボタンコントロールをダブルクリックするだけで実装できてしまうため、コード自体を目にする機会もありません。(裏ではイベントを実行するコードが追加されています)

イベントの基本については次のページも見てください

VisualStudioでボタンを配置した時の内部処理を見てみましょう

フォーム設計画面で、ボタンを配置、クリックイベントを作成

まず、ボタンを1つ置いてダブルクリックします

自動生成されたコードを確認

InitializeComponentメソッドが自動作成されているので、このメソッド本体に移動します
名前の上でマウスを右クリックして移動

イベントに関係するコードを抜き出します

button1.Click += new EventHandler(button1_Click);

private void button1_Click(object sender, EventArgs e)
{
}

イベントを自作してみる

ボタンをコードで生成

new EventHandler(button1_Click);は、新しいC#では次のように省略できます

Button button = new Button();
button.Click += MyButtonClick;

private void MyButtonClick(object sender, EventArgs e)
{
}

MyButtonClickという名前がなくなりました。今回はどのようにイベントが実行されるのかが判ればいい(他から呼ばれる可能性がない場合)

Button button = new Button();
button.Click += (sender, e) =>
{
};

動作するように加工

Labelコンポーネントを追加しておいてください

動作するように少し加工します

Button button = new Button();
button.Parent = this;
button.Click += MyButtonClick;

private void MyButtonClick(object sender, EventArgs e)
{
    label1.Text = "押された";
}

全てのコード

using System;
using System.Windows.Forms;

namespace EventForBrog
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            Button button = new Button();
            button.Parent = this;
            button.Click += MyButtonClick;
        }

        private void MyButtonClick(object sender, EventArgs e)
        {
            label1.Text = "押された";
        }
    }
}

実行結果

もっと自作

.Netのフレームワークではなく、ピュアC#で作成

EventHandlerをnewしてますが、これの定義を見ると次のようになっています
delegateは、メソッドのシグネチャの定義なので、

2つの引数(object型とEventArgs型)を持ち、戻り値がないメソッドの形となります

public delegate void EventHandler(object sender, EventArgs e);

自作してみます。簡単にするため、引数はint型で1つとします

public delegate void MyEvent(int a);

 次にClickプロパティの定義を見てみると次のようになっています

public event EventHandler Click
{
    add
    {
        base.Events.AddHandler(EventClick, value);
    }
    remove
    {
        base.Events.RemoveHandler(EventClick, value);
    }
}

AddHandlerメソッドの定義に踏み込んで・・・となると、さすがに深いので次のように思い切って簡略化します

public event MyEvent myEvent;

もうシンプルに、イベントだけ残して、あとは消すと・・・
ここで、Invokeメソッドは登録されたイベントを実行する指示になります

using System;
using System.Windows.Forms;

namespace EventForBrog
{
    public delegate void MyEvent(int a);

    public partial class Form1 : Form
    {
        public event MyEvent myEvent;

        public Form1()
        {
            InitializeComponent();

            myEvent += ShowMsg;
            myEvent.Invoke(1);
        }

        private void ShowMsg(int a)
        {
            label1.Text = $"{a}が渡されたイベント";
        }
    }
}

実際に使う方法

myEvent += ShowMsg;
myEvent.Invoke(1);

を設計上で必要なところに移動し、状況によって呼び出すメソッド(イベントハンドラ)を変えます
+=では代入演算子で、メソッドを加算できます(つまり一気に複数のメソッドを実行できる)
Invokeメソッドは、イベントを実行するので、この2つのコードは別々のところに書いておけばいいです

応用

実際のアプリケーションに近いものを学習用に用意しました