どの様なやり方があるのか、調べてみた。
準備
新しいプロジェクトを作成
↓

「Form1」へ
「ツールボックス」から
「Button」と「TextBox」を配置
↓

「プロジェクト」->「新しい項目の追加」
で「Windowsフォーム」を追加する。
↓

追加した「Form2」へ
「ツールボックス」から
「TextBox」を配置
↓

「Form1」のボタンをダブルクリックして、
「クリック時イベント」のコードを表示させておきます。
1 2 3 4 | private void button1_Click( object sender, EventArgs e) { } |
「Form1」からモーダルで「Form2」を呼び出す
モーダルで「Form2」を呼び出すには2つの方法があります。
普段はリソースの解放が自動で行われる「using」の方を使います。
事情により使い分けます。
1 2 3 4 5 6 | private void button1_Click( object sender, EventArgs e) { var subForm = new Form2(); subForm.ShowDialog(); subForm.Dispose(); } |
1 2 3 4 5 6 7 | private void button1_Click( object sender, EventArgs e) { using (var subForm = new Form2()) { subForm.ShowDialog(); } } |
一度ここ迄で実行してみましょう。
ボタンを押すと「Form2」がモーダルで実行されるはずです。
Form間でデータの受け渡しを行う
「Form1」と「Form2」の間でデータの受け渡しを行います。
「Form2」へ
「ツールボックス」から
「Button」を配置して下さい。

「Form2」の配置したボタンをダブルクリックして、
「クリック時イベント」のコードを表示させておきます。
1 2 3 4 | private void button1_Click( object sender, EventArgs e) { } |
「Form2」デザインのイベントから
「FormClosing」をダブルクリックして、
「Form終了時イベント」のコードを表示させておきます。

↓
1 2 3 4 | private void Form2_FormClosing( object sender, FormClosingEventArgs e) { } |
準備が出来たので、
Form間でのデータ受け渡しの
いくつかのパターンを記載します。
●パターンA
「Form2」側で「Form1」のインスタンスを取得して、「Form1」の持っているデータの取得や設定をしたいので、
以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | public partial class Form1 : Form { //Form1インスタンス格納用 private static Form1 _form1Instance; public Form1() { InitializeComponent(); //Form1インスタンスを格納する _form1Instance = this ; } //Form1インスタンスを設定、取得する。 public static Form1 Form1Instance { get => _form1Instance; set => _form1Instance = value; } //テキストボックスへテキストを設定、取得する。 public string TextBoxText { get => textBox1.Text; set => textBox1.Text = value; } private void button1_Click( object sender, EventArgs e) { using (var subForm = new Form2()) { //Form2表示 subForm.ShowDialog(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | public partial class Form2 : Form { //Form1インスタンス格納用 private Form1 form1Instance; public Form2() { InitializeComponent(); //Form1のインスタンスを取得 form1Instance = Form1.Form1Instance; //Form1のテキストボックス文字列を //Form2のテキストボックス文字列へ設定 textBox1.Text = form1Instance.TextBoxText; } private void button1_Click( object sender, EventArgs e) { this .Close(); } private void Form2_FormClosing( object sender, FormClosingEventArgs e) { //Form2のテキストボックス文字列を //Form1のテキストボックス文字列へ設定 form1Instance.TextBoxText = textBox1.Text; } } |
Form間でデータの受け渡しができるハズです。
このパターンAの方法だと、
「Form1」に自身のインスタンスの格納用メンバを用意して、
それに対してstaticを適用しています。
1つの「Form1」しか同時に使用しない場合はこれで大丈夫ですが、
複数の「Form1」のインスタンスを同時に使用する場合、
インスタンスの格納用メンバがstaticの為、
クラス内でstatic部分が共有されてしまい、
うまく動きません。
ですが、
普通は同一Formを複数同時に使う事はないので、
これでも問題ありません。
●パターンB
「Form1」から「Form2」をnewする際に「Form1」のインスタンスを「Form2」へ
引数として渡す事により、
「Form2」から
「Form1」の持っているデータの取得や設定をしたいので、
以下のようにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public partial class Form1 : Form { public Form1() { InitializeComponent(); } //テキストボックスへテキストを設定、取得する。 public string TextBoxText { get => textBox1.Text; set => textBox1.Text = value; } private void button1_Click( object sender, EventArgs e) { using (var subForm = new Form2( this )) { //Form2表示 subForm.ShowDialog(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public partial class Form2 : Form { //Form1インスタンス格納用 private Form1 form1Instance; public Form2(Form1 form1Instance) { InitializeComponent(); //Form1のインスタンスを取得 this .form1Instance = form1Instance; //Form1のテキストボックス文字列を //Form2のテキストボックス文字列へ設定 textBox1.Text = this .form1Instance.TextBoxText; } private void button1_Click( object sender, EventArgs e) { this .Close(); } private void Form2_FormClosing( object sender, FormClosingEventArgs e) { //Form2のテキストボックス文字列を //Form1のテキストボックス文字列へ設定 form1Instance.TextBoxText = textBox1.Text; } } |
「Form1」からstaticが無くなり、
いくらかすっきりしました。
Form間のデータ受け渡し内容がシンプルな物であれば、
このパターンを使用するのがよさそうです。
これなら複数Formのインスタンスを作らなくては
いけない場合でも問題無く動きそうです。
●パターンC
「Form2」側に自身でダイアログを生成して、表示させる自家製メソッドをstaticで用意。
引数と戻り値にリストを使用する事により、
フォーム間でデータの受け渡しを行います。
「Form1」側は「Form2」へ渡したいデータをリスト化し、
「Form2」自家製メソッドを引数付きで呼びます。
「Form2」のフォーム表示後、戻り値のリストを取り出し、
「Form1」内で利用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click( object sender, EventArgs e) { //Form2への受け渡し用配列を作成 var sendList = new List< object >(); sendList.Add(( string )textBox1.Text); //Form2を表示して戻り値を受け取る。 List< object > resultObjs = Form2.ShowForm2(sendList); //Form2から受け取ったテキストを戻す textBox1.Text = ( string )resultObjs[0]; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | public partial class Form2 : Form { //Form1から受け取ったオブジェクト配列 private List< object > argObjs = new List< object >(); //Form1へ返す戻り値用オブジェクト配列 public List< object > resultObjs = new List< object >(); //コンストラクタで //複数の様々な型をオブジェクト配列で受け取る。 public Form2(List< object > argObjs) { InitializeComponent(); //自身のメンバへ格納 this .argObjs = argObjs; //Form1のテキストボックス文字列を //Form2のテキストボックス文字列へ設定 textBox1.Text = ( string ) this .argObjs[0]; } //Form2のインスタンス作成用自家製メソッド static public List< object > ShowForm2(List< object > argObjs) { //Form2を生成 using (Form2 subForm= new Form2(argObjs)) { subForm.ShowDialog(); //表示 //戻り値用オブジェクト配列を返す return subForm.resultObjs; } } private void button1_Click( object sender, EventArgs e) { this .Close(); } private void Form2_FormClosing( object sender, FormClosingEventArgs e) { //Form2のテキストボックス文字列を //戻り値用オブジェクト配列へ代入 resultObjs.Add(textBox1.Text); } } |
受け渡したいデータが増えても、
「Form1」側に無駄にpublicが増えず、
格納するデータの順番さえちゃんと管理できれば楽そうです。
「Form2」自身で自分のインスタンスの生成、表示をやってくれるので
「Form1」側から見たときに、使いやすそうです。