C#でフォーム間でデータや値の受け渡しをする
C#でフォーム間でデータの受け渡しをする方法を紹介します。
概要
フォーム間でデータの受け渡しをするコードを紹介します。いくつかの方法があります。
- 共有先のフォームのプロパティ、メンバ変数に値を設定する、またはメソッドを呼び出す
- フォームオブジェクトを共有先のフォームから参照できるようにする
- Progamクラスのメンバ変数を利用する
- 共有メモリ、ファイルで値を渡す
- Dependency Injection (DI)で値を渡す
相手のフォームのプロパティ、メンバ変数に値を設定する、またはメソッドを呼び出す
フォーム間でデータの交換をする場合によく使われる方法です。
送信側のフォームから受信側のフォームのメソッドを呼び出すか、プロパティに代入します。
サブフォーム側から、メインフォームへの呼び出しが無ければ、依存関係は低くできます。
一方でサブフォームから呼び出し元のフォームに値を設定したり、フォームのクラスのメソッドを実行する場合には、
サブフォームのメンバ変数に呼び出し元のフォームのオブジェクトを代入するか、サブフォームのOwnerプロパティに呼び出し元のフォームを設定して、サブフォームから
メインフォームのオブジェクトを参照できるようにする必要があります。
サブフォームから、メインフォームへの参照を追加すると、依存関係は高くなってしまいます。
フォームオブジェクトを共有先のフォームから参照できるようにする
先の方法と似ていますが、値を設定するのではなく、フォームオブジェクトを参照できるようにする方法です。
Publicで定義されているもののみが操作できるため、アクセス識別子を厳しく設定すれば、依存関係は比較的弱くできるかと思われます。
Progamクラスのメンバ変数を利用する
Programクラスにメンバ変数を宣言して、その変数を共有する方法です。
Programクラスの変数がグローバル変数的な意味合いになってしまうため、依存関係は強くなってしまいます。
共有メモリ、ファイルを利用する
共有メモリやファイルを利用する方法です。
ファイルを利用する方法はこの記事では紹介しません。
共有メモリについては
こちらの記事を参照してください。
Dependency Injection (DI)で値を渡す
Dependency Injection (DI)を利用する方法です。この記事では紹介しません。
詳しくは
こちらの記事を参照してください。
比較
それぞれの方式の特徴方式 | コードの記述量 | 値の一意性 | サブフォームからメインフォームの呼び出し | 相互依存度 |
プロパティ、メンバ変数に値を設定 | 小 | △ | △ | 中 |
フォームオブジェクトを共有 | 小 | 〇 | 〇 | 高 |
Progamクラス | 小 | 〇 | △ | 中 |
共有メモリ、ファイルを利用 | 中 | △ | △ | 低 |
Dependency Injection (DI) | 中 | 〇 | △ | 低 |
プログラム: プロパティ、メンバ変数に値を設定する方法
UI
下図のUIを作成します。
FormMain
ボタンとラベルを配置します。
FormSub
メインのフォームと同様に、ボタンとラベルを配置します。
コード
以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MultiFormDataTransfer
{
public partial class FormMain : Form
{
private string receiveData ="";
FormSub fs;
public FormMain()
{
InitializeComponent();
fs = new FormSub();
fs.formMain = this;
}
private void button1_Click(object sender, EventArgs e)
{
fs.SendData = "Penguin";
}
public string ReceiveData
{
set
{
receiveData = value;
label1.Text = receiveData;
}
get
{
return receiveData;
}
}
private void FormMain_Shown(object sender, EventArgs e)
{
fs.Show();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MultiFormDataTransfer
{
public partial class FormSub : Form
{
private string sendData="";
public FormMain formMain;
public FormSub()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (formMain != null) {
formMain.ReceiveData = "Duck";
}
}
public string SendData
{
set
{
sendData = value;
label1.Text = sendData;
}
get
{
return sendData;
}
}
}
}
解説
メインフォームが表示されたタイミングで、サブフォームを表示します。
作成したサブフォームのインスタンスはメインフォームに保持します。
サブフォームからメインフォームに値を戻す際に、メインフォームのオブジェクトを参照する必要があるため、Ownerプロパティにメインフォームのオブジェクトを設定します。
public FormMain()
{
InitializeComponent();
fs = new FormSub();
fs.Owner = this;
}
メインフォームのボタンがクリックされると、サブフォームのクラスのSendDataプロパティに値を代入してサブフォームに値を渡します。
private void button1_Click(object sender, EventArgs e)
{
fs.SendData = "Penguin";
}
サブフォームの
SendData
プロパティでは、値をメンバ変数に格納後、ラベルに受け取った値を表示します。
public string SendData
{
set
{
sendData = value;
label1.Text = sendData;
}
get
{
return sendData;
}
}
サブフォームのボタンがクリックされた場合は、Ownerプロパティからメインフォームのオブジェクトを取得し、メインフォームのプロパティに値を代入します。
private void button1_Click(object sender, EventArgs e)
{
FormMain fm = (FormMain)this.Owner;
if (fm != null) {
fm.ReceiveData = "Duck";
}
}
フォーム間で情報を交換する場合、メインフォームからサブフォームへの受け渡しの場合はメインフォームではサブフォームのインスタンス変数を保持しているため、
サブフォームのpublicメンバ変数を用いたり、プロパティを用いて情報を交換できます。
一方サブフォームからメインフォームへ情報を受け渡す場合、サブフォームはメインフォームのインスタンスを保持していないため、
サブフォームの呼び出し時にメインフォームのインスタンスをサブフォームの変数に渡すか、もしくはOwnerプロパティを設定し、
サブフォームにメインフォームのインスタンスを伝える必要があります。
実行結果
プロジェクトを実行します。フォームが2つ表示されます。
メインのフォームの[button1]をクリックします。サブのフォームのラベルに"Penguin"の文字列が表示されます。メインのフォームで代入した値がサブフォームに反映されています。
サブフォームの[button1]ボタンをクリックします。メインフォームのラベルに"Duck"の文字列が表示されます。サブのフォームで代入した値がメインフォームのラベルに反映されます。
補足 : Ownerプロパティを用いる例
先のコードと同様の処理ですが、Ownerプロパティを用いた場合の実装コードは次の通りです。
以下のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MultiFormDataTransfer
{
public partial class FormMain : Form
{
private string receiveData ="";
FormSub fs;
public FormMain()
{
InitializeComponent();
fs = new FormSub();
fs.Owner = this;
}
private void button1_Click(object sender, EventArgs e)
{
fs.SendData = "Penguin";
}
public string ReceiveData
{
set
{
receiveData = value;
label1.Text = receiveData;
}
get
{
return receiveData;
}
}
private void FormMain_Shown(object sender, EventArgs e)
{
fs.Show();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace MultiFormDataTransfer
{
public partial class FormSub : Form
{
private string sendData="";
public FormMain formMain;
public FormSub()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
FormMain fm = (FormMain)this.Owner;
if (fm != null) {
fm.ReceiveData = "Duck";
}
}
public string SendData
{
set
{
sendData = value;
label1.Text = sendData;
}
get
{
return sendData;
}
}
}
}
解説
メインフォームが表示されたタイミングで、サブフォームを表示します。
作成したサブフォームのインスタンスはメインフォームに保持します。
サブフォームからメインフォームに値を戻す際に、メインフォームのオブジェクトを参照する必要があるため、Ownerプロパティにメインフォームのオブジェクトを設定します。
public FormMain()
{
InitializeComponent();
fs = new FormSub();
fs.Owner = this;
}
メインフォームのボタンがクリックされると、サブフォームのクラスのSendDataプロパティに値を代入してサブフォームに値を渡します。
private void button1_Click(object sender, EventArgs e)
{
fs.SendData = "Penguin";
}
サブフォームの
SendData
プロパティでは、値をメンバ変数に格納後、ラベルに受け取った値を表示します。
public string SendData
{
set
{
sendData = value;
label1.Text = sendData;
}
get
{
return sendData;
}
}
サブフォームのボタンがクリックされた場合は、Ownerプロパティからメインフォームのオブジェクトを取得し、メインフォームのプロパティに値を代入します。
private void button1_Click(object sender, EventArgs e)
{
FormMain fm = (FormMain)this.Owner;
if (fm != null) {
fm.ReceiveData = "Duck";
}
}
プログラム: フォームのオブジェクトを参照する方法
先の方法と仕組みは同じです。値をプロパティやメンバ変数に設定せずに、フォームのオブジェクトを参照できる状態にします。
UI
下図のUIを作成します。
FormMain
ボタンとラベルを配置します。
FormSub
メインのフォームと同様に、ボタンとラベルを配置します。
コード
下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiFormDataTransferRO
{
public partial class FormMain : Form
{
private FormSub fs;
public string DataString { get; set; }
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
DataString = "かるがもサブレ";
if (fs != null) {
fs.UpdateData();
}
}
private void FormMain_Shown(object sender, EventArgs e)
{
fs = new FormSub();
fs.Show();
fs.formMain = this;
}
public void UpdateData()
{
label1.Text = DataString;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiFormDataTransferRO
{
public partial class FormSub : Form
{
public FormMain formMain { get; set; }
public FormSub()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (formMain != null) {
formMain.DataString = "しろくまアイス";
formMain.UpdateData();
}
}
public void UpdateData()
{
if (formMain != null) {
label1.Text = formMain.DataString;
}
}
}
}
解説
メインのフォームのクラスのみにプロパティ(DataString)を宣言します。
public string DataString { get; set; }
メインフォームが表示された直後にサブフォームを表示します。サブフォームからメインフォームにアクセスできるよう、
サブフォームの formMain プロパティにメインフォームのオブジェクトを代入します。
private void FormMain_Shown(object sender, EventArgs e)
{
fs = new FormSub();
fs.Show();
fs.formMain = this;
}
ボタンのクリックで値を自分のオブジェクトのプロパティ(DataString)に代入します。
代入後にサブフォームの
UpdateData()
メソッドを呼び出して値をラベルの表示に反映します。
private void button1_Click(object sender, EventArgs e)
{
DataString = "かるがもサブレ";
if (fs != null) {
fs.UpdateData();
}
}
UpdateData()イベントでメインフォームのDataStringプロパティに代入されている値をラベルに表示します。
public void UpdateData()
{
if (formMain != null) {
label1.Text = formMain.DataString;
}
}
サブフォームからメインフォームへの値の渡し方は、サブフォームからメインフォームのオブジェクトを参照できるため、
メインフォームのオブジェクトの DataString プロパティに代入して値を渡します。
代入後にメインフォームの
UpdateData()
メソッドを呼び出して値をラベルの表示に反映します。
private void button1_Click(object sender, EventArgs e)
{
if (formMain != null) {
formMain.DataString = "しろくまアイス";
formMain.UpdateData();
}
}
UpdateData()イベントでDataStringプロパティに代入されている値をラベルに表示します。
public void UpdateData()
{
label1.Text = DataString;
}
実行結果
プロジェクトを実行します。2つのフォームが表示されます。
メインフォームの[button1]ボタンをクリックします。サブフォームのラベルに「かるがもサブレ」の文字列が表示されます。
メインフォームのコードで代入した値がサブフォームのラベルに反映されます。
サブフォームの[button1]ボタンをクリックします。メインフォームのラベルに「しろくまアイス」の文字列が表示されます。
サブフォームのコードで代入した値がメインフォームのラベルに反映されます。
プログラム: Program クラスのメンバ変数を利用する方法
値の受け渡しのみをする場合には、Programクラスのメンバ変数を利用する方法もあります。
UI
下図のフォームを作成します。
メインのフォームにはボタンとラベルを配置します。
サブのフォームにもラベルとボタンを配置します。
コード
下記のコードを記述します。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiFormDataTransferPC
{
static class Program
{
static public string TransferText;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new FormMain());
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiFormDataTransferPC
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Program.TransferText = "ぺんぎんクッキー";
FormSub fs = new FormSub();
fs.ShowDialog(this);
label1.Text = Program.TransferText;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MultiFormDataTransferPC
{
public partial class FormSub : Form
{
public FormSub()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Program.TransferText = "らくだキャラメル";
DialogResult = DialogResult.OK;
}
private void FormSub_Shown(object sender, EventArgs e)
{
label1.Text = Program.TransferText;
}
}
}
解説
Programクラスにメンバ変数
TransferText
を宣言します。
static class Program
{
static public string TransferText;
/* 中略 */
}
FormMain の[button1]をクリックすると下記のコードを実行します。Programクラスの
TransferText
変数に受け渡す値を代入します。
代入後に別のフォーム FormSub のインスタンスを作成しフォームを表示します。
サブのフォームはモーダルで表示します。コードの詳細は
こちらの記事を参照してください。
private void button1_Click(object sender, EventArgs e)
{
Program.TransferText = "ぺんぎんクッキー";
FormSub fs = new FormSub();
fs.ShowDialog(this);
label1.Text = Program.TransferText;
}
FormSubではフォーム表示後に、Programクラスの
TransferText
変数の値をフォームのラベルに表示します。
private void FormSub_Shown(object sender, EventArgs e)
{
label1.Text = Program.TransferText;
}
FormSubのボタンをクリックすると、Programクラスの
TransferText
変数の値を変更し、DialogResultに値を設定してフォームを閉じます。
private void button1_Click(object sender, EventArgs e)
{
Program.TransferText = "らくだキャラメル";
DialogResult = DialogResult.OK;
}
実行結果
プロジェクトを実行します。メインのフォーム(FormMain)が表示されます。
フォームの[button1]をクリックします。サブフォームが表示され、サブフォームのラベルにメインのフォームで設定した「ぺんぎんクッキー」の文字列が表示されます。
メインフォームの値をサブフォームに渡すことができました。
サブフォーム(FormSub)の[Close]ボタンをクリックします。
ボタンをクリックすると、サブフォームが閉じ、メインフォームのラベルにサブフォームで設定した「らくだキャラメル」の文字列が表示されます。
サブフォームの値をメインフォームで参照できました。
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2012-04-24
改訂日: 2021-08-15