イベントハンドラをまとめる
同じようなボタンがたくさんあって、その中で同じようなコードを記述している場合、コードをまとめたくなりませんか。その具体的な手法を紹介します。
なんの工夫もないコード(改善前のコード)
下記のコードはフォームにボタンが8個配置されており、それを押すと MessageBox.Show() で数値 Value がダイアログ表示されます。
なんの工夫もなくコードを書くとこのようになります。初心者むけのプログラミング解説本などは、こういう書き方が多いですよね。
ダラダラと同じことが書かれています。これをなんとか共通化できないかと思うのはプログラマなら当然の習性だと思います。
using System;
using System.Windows.Forms;
namespace aaa
{
public partial class Form1 : Form
{
int Value = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
}
private void button1_Click( object sender, EventArgs e )
{
Value = 1;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button2_Click( object sender, EventArgs e )
{
Value = 2;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button3_Click( object sender, EventArgs e )
{
Value = 3;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button4_Click( object sender, EventArgs e )
{
Value = 4;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button5_Click( object sender, EventArgs e )
{
Value = 5;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button6_Click( object sender, EventArgs e )
{
Value = 6;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button7_Click( object sender, EventArgs e )
{
Value = 7;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
private void button8_Click( object sender, EventArgs e )
{
Value = 8;
MessageBox.Show( String.Format( "Value is {0}", Value ) );
}
}
}
そのときの Form1.Designer.cs は下記のコードのようになっているはずです。ボタンのクリックとイベントが結び付けられているところはコード内のコメントにも書いてありますが
this.button1.Click += new System.EventHandler(this.button1_Click); // 49行目.
this.button2.Click += new System.EventHandler(this.button2_Click); // 59行目.
this.button3.Click += new System.EventHandler(this.button3_Click); // 69行目.
this.button4.Click += new System.EventHandler(this.button4_Click); // 79行目.
this.button5.Click += new System.EventHandler(this.button5_Click); // 89行目.
this.button6.Click += new System.EventHandler(this.button6_Click); // 99行目.
this.button7.Click += new System.EventHandler(this.button7_Click); // 109行目.
this.button8.Click += new System.EventHandler(this.button8_Click); // 119行目.
というところにご注目ください。
namespace aaa
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.button7 = new System.Windows.Forms.Button();
this.button8 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(80, 48);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button2
//
this.button2.Location = new System.Drawing.Point(176, 48);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button3
//
this.button3.Location = new System.Drawing.Point(272, 48);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 2;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.button3_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button4
//
this.button4.Location = new System.Drawing.Point(368, 48);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 23);
this.button4.TabIndex = 3;
this.button4.Text = "button4";
this.button4.UseVisualStyleBackColor = true;
this.button4.Click += new System.EventHandler(this.button4_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button5
//
this.button5.Location = new System.Drawing.Point(80, 80);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(75, 23);
this.button5.TabIndex = 4;
this.button5.Text = "button5";
this.button5.UseVisualStyleBackColor = true;
this.button5.Click += new System.EventHandler(this.button5_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button6
//
this.button6.Location = new System.Drawing.Point(176, 80);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(75, 23);
this.button6.TabIndex = 5;
this.button6.Text = "button6";
this.button6.UseVisualStyleBackColor = true;
this.button6.Click += new System.EventHandler(this.button6_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button7
//
this.button7.Location = new System.Drawing.Point(272, 80);
this.button7.Name = "button7";
this.button7.Size = new System.Drawing.Size(75, 23);
this.button7.TabIndex = 6;
this.button7.Text = "button7";
this.button7.UseVisualStyleBackColor = true;
this.button7.Click += new System.EventHandler(this.button7_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// button8
//
this.button8.Location = new System.Drawing.Point(368, 80);
this.button8.Name = "button8";
this.button8.Size = new System.Drawing.Size(75, 23);
this.button8.TabIndex = 7;
this.button8.Text = "button8";
this.button8.UseVisualStyleBackColor = true;
this.button8.Click += new System.EventHandler(this.button8_Click); // ここがイベントハンドラとボタンクリックが関連づけられているところ.
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button8);
this.Controls.Add(this.button7);
this.Controls.Add(this.button6);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button8;
}
}
カンのいい人ならば、ここのイベントハンドラとの関連付けをうまくやれば、なんとかなるのではないか、と思いますよね。
もちろんなんとかなります。では、次に改善案をご提示します。
イベントハンドラをまとめる( Form1.Designer.cs で関連付ける方法)
まずは、Form1.cs に buttonN_Click という名前のメソッドを作ってください。ここのメソッド命名の N は番号みたいなイメージです。ユーザの好みでわかりやすい名前をつけてください。
このメソッドがどのコントロールからコールされたかを判断して Value に 1 ~ 8 の値を入れてやります。buttonN_Click() の引数の sender に、どのコントロールからコールされたか手がかりが入っています。
共通化によってコード量が激減したことがわかると思います。
using System;
using System.Windows.Forms;
namespace aaa
{
public partial class Form1 : Form
{
int Value = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load( object sender, EventArgs e )
{
}
private void buttonN_Click( object sender, EventArgs e )
{
if ( sender == button1 ){ Value = 1; }
else if ( sender == button2 ){ Value = 2; }
else if ( sender == button3 ){ Value = 3; }
else if ( sender == button4 ){ Value = 4; }
else if ( sender == button5 ){ Value = 5; }
else if ( sender == button6 ){ Value = 6; }
else if ( sender == button7 ){ Value = 7; }
else if ( sender == button8 ){ Value = 8; }
else { return; }
String msg = String.Format( "Value is {0}", Value );
String cap = "buttonN_Click";
MessageBox.Show( msg, cap );
}
}
}
このとき Form1.Designer.cs は下記のように書き換えます。
this.button1.Click += new System.EventHandler(this.buttonN_Click); // 49行目.
this.button2.Click += new System.EventHandler(this.buttonN_Click); // 59行目.
this.button3.Click += new System.EventHandler(this.buttonN_Click); // 69行目.
this.button4.Click += new System.EventHandler(this.buttonN_Click); // 79行目.
this.button5.Click += new System.EventHandler(this.buttonN_Click); // 89行目.
this.button6.Click += new System.EventHandler(this.buttonN_Click); // 99行目.
this.button7.Click += new System.EventHandler(this.buttonN_Click); // 109行目.
this.button8.Click += new System.EventHandler(this.buttonN_Click); // 119行目.
Form1.Designer.cs の具体的なコードは下記のようになります。
namespace aaa
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.button7 = new System.Windows.Forms.Button();
this.button8 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(80, 48);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button2
//
this.button2.Location = new System.Drawing.Point(176, 48);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button3
//
this.button3.Location = new System.Drawing.Point(272, 48);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 2;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
this.button3.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button4
//
this.button4.Location = new System.Drawing.Point(368, 48);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 23);
this.button4.TabIndex = 3;
this.button4.Text = "button4";
this.button4.UseVisualStyleBackColor = true;
this.button4.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button5
//
this.button5.Location = new System.Drawing.Point(80, 80);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(75, 23);
this.button5.TabIndex = 4;
this.button5.Text = "button5";
this.button5.UseVisualStyleBackColor = true;
this.button5.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button6
//
this.button6.Location = new System.Drawing.Point(176, 80);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(75, 23);
this.button6.TabIndex = 5;
this.button6.Text = "button6";
this.button6.UseVisualStyleBackColor = true;
this.button6.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button7
//
this.button7.Location = new System.Drawing.Point(272, 80);
this.button7.Name = "button7";
this.button7.Size = new System.Drawing.Size(75, 23);
this.button7.TabIndex = 6;
this.button7.Text = "button7";
this.button7.UseVisualStyleBackColor = true;
this.button7.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// button8
//
this.button8.Location = new System.Drawing.Point(368, 80);
this.button8.Name = "button8";
this.button8.Size = new System.Drawing.Size(75, 23);
this.button8.TabIndex = 7;
this.button8.Text = "button8";
this.button8.UseVisualStyleBackColor = true;
this.button8.Click += new System.EventHandler(this.buttonN_Click); // ここを書き換えた.
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button8);
this.Controls.Add(this.button7);
this.Controls.Add(this.button6);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button8;
}
}
イベントハンドラをまとめる( Form1.cs の初期段階で関連付ける方法)
Form1.Designer.cs は、フォームデザイナに関する重要なコードですので、あまり手動で書き換えるのはおすすめできません。
わたくしのおすすめは Form1_Load() のところなどのアプリケーション起動の初期で、ボタンクリックのコードとイベントハンドラを関連づけるやりかたです。もちろん Form1() のコンストラクタのところでもいいです。
using System;
using System.Windows.Forms;
namespace aaa
{
public partial class Form1 : Form
{
int Value = 0;
public Form1()
{
// ここで関連付けてもいい.
InitializeComponent();
// ここで関連付けてもいい.
}
private void Form1_Load( object sender, EventArgs e )
{
// ユーザによってボタンクリックがされるまでに関連づけておく.
this.button1.Click += new System.EventHandler(this.buttonN_Click);
this.button2.Click += new System.EventHandler(this.buttonN_Click);
this.button3.Click += new System.EventHandler(this.buttonN_Click);
this.button4.Click += new System.EventHandler(this.buttonN_Click);
this.button5.Click += new System.EventHandler(this.buttonN_Click);
this.button6.Click += new System.EventHandler(this.buttonN_Click);
this.button7.Click += new System.EventHandler(this.buttonN_Click);
this.button8.Click += new System.EventHandler(this.buttonN_Click);
}
private void buttonN_Click( object sender, EventArgs e )
{
if ( sender == button1 ){ Value = 1; }
else if ( sender == button2 ){ Value = 2; }
else if ( sender == button3 ){ Value = 3; }
else if ( sender == button4 ){ Value = 4; }
else if ( sender == button5 ){ Value = 5; }
else if ( sender == button6 ){ Value = 6; }
else if ( sender == button7 ){ Value = 7; }
else if ( sender == button8 ){ Value = 8; }
else { return; }
String msg = String.Format( "Value is {0}", Value );
String cap = "buttonN_Click";
MessageBox.Show( msg, cap );
}
}
}
そのときの Form1.Designer.cs では、ボタンクリックとイベントハンドラが関連づけられていないことを確認してください。こんな感じです。
namespace aaa
{
partial class Form1
{
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージド リソースを破棄する場合は true を指定し、その他の場合は false を指定します。</param>
protected override void Dispose( bool disposing )
{
if ( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.button7 = new System.Windows.Forms.Button();
this.button8 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(80, 48);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button2
//
this.button2.Location = new System.Drawing.Point(176, 48);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 1;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button3
//
this.button3.Location = new System.Drawing.Point(272, 48);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(75, 23);
this.button3.TabIndex = 2;
this.button3.Text = "button3";
this.button3.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button4
//
this.button4.Location = new System.Drawing.Point(368, 48);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 23);
this.button4.TabIndex = 3;
this.button4.Text = "button4";
this.button4.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button5
//
this.button5.Location = new System.Drawing.Point(80, 80);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(75, 23);
this.button5.TabIndex = 4;
this.button5.Text = "button5";
this.button5.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button6
//
this.button6.Location = new System.Drawing.Point(176, 80);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(75, 23);
this.button6.TabIndex = 5;
this.button6.Text = "button6";
this.button6.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button7
//
this.button7.Location = new System.Drawing.Point(272, 80);
this.button7.Name = "button7";
this.button7.Size = new System.Drawing.Size(75, 23);
this.button7.TabIndex = 6;
this.button7.Text = "button7";
this.button7.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// button8
//
this.button8.Location = new System.Drawing.Point(368, 80);
this.button8.Name = "button8";
this.button8.Size = new System.Drawing.Size(75, 23);
this.button8.TabIndex = 7;
this.button8.Text = "button8";
this.button8.UseVisualStyleBackColor = true;
// ボタンクリックとイベントハンドラが関連づけられているコードがないようにする.
// もし関連付けられていたらその行を削除する.
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.button8);
this.Controls.Add(this.button7);
this.Controls.Add(this.button6);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
private System.Windows.Forms.Button button7;
private System.Windows.Forms.Button button8;
}
}
プロパティエディタを使って関連付ける方法もありますが、イベントハンドラ関連付けのコードの仕組みが隠蔽され解説にむかないので紹介しませんでした。
仕組みはどうでもいい、とりあえず急いでなんとかしたいという場合はウェブ検索で "C#" "EventHandler" "まとめる" "共通化" みたいなキーワードを使って調べてみてください。
いまどきなら ChatGPT などの対話型 AI に聞くのもいいですね。