親ウィンドウから子ウィンドウを作成し、データの受け渡しを行う方法

2024年8月22日

この技術資料では、親ウィンドウから子ウィンドウを生成し、子ウィンドウで入力したデータを親ウィンドウに渡す方法を解説します。特に、複数の親ウィンドウが存在する場合に、子ウィンドウがどの親ウィンドウともデータをやり取りできる方法についても説明します。

目次

  1. 親と子が1対1のケース
  2. 親が複数で子が1のケース

親と子が1対1のケース

準備

親ウィンドウ (Form1)

  • Labelコンポーネント (label1)
  • Buttonコンポーネント (button1)

子ウィンドウ (Form2)

  • Buttonコンポーネント (button2)

親ウィンドウ (Form1) のコード

using System;
using System.Windows.Forms;

namespace FormDataTrans
{
    public partial class Form1 : Form
    {
        public string Msg
        {
            get => label1.Text;
            set => label1.Text = value;
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            // 子ウィンドウをモーダルダイアログとして表示
            new Form2(this).ShowDialog();
        }
    }
}

このコードでは、Form1 の Button1 をクリックすると Form2 が表示されます。Form2 は、Form1 のインスタンスを引数として受け取り、そのインスタンスを使用してデータを親ウィンドウに渡します。

子ウィンドウ (Form2) のコード

using System;
using System.Windows.Forms;

namespace FormDataTrans
{
    public partial class Form2 : Form
    {
        private Form1 form1;

        public Form2(Form1 form1)
        {
            InitializeComponent();
            this.form1 = form1;
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            // 親ウィンドウのLabelにデータを渡す
            form1.Msg = "ボタンが押されました";
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            // 親ウィンドウに子ウィンドウが閉じられたことを通知
            form1.Msg = "Form2が閉じられました";
        }
    }
}

このコードでは、Form2 の Button2 をクリックすると、Form1 の label1 のテキストが更新されます。また、Form2 が閉じられると、Form1 のテキストも更新されます。

実行結果

  1. Form1 の button1 をクリックすると、Form2 ウィンドウが作成されます。
  2. Form2 の button2 をクリックすると、Form1 の label1 の表示が「ボタンが押されました」に変わります。
  3. Form2 を閉じると、Form1 の label1 の表示が「Form2が閉じられました」に変わります。

親が複数で子が1のケース

子ウィンドウがどの親ウィンドウから作成されたかに応じてデータを受け渡す方法

準備

親1ウィンドウ (Form1)

  • Labelコンポーネント (label1)
  • Buttonコンポーネント (button1) – Form2 を生成
  • Buttonコンポーネント (button2) – Form3 を生成

親2ウィンドウ (Form3)

  • Labelコンポーネント (label1)
  • Buttonコンポーネント (button1) – Form2 を生成

子ウィンドウ (Form2)

  • Buttonコンポーネント (button2) – 生成元フォームの Label を変更

インターフェース IDummyData

namespace FormDataTrans
{
    interface IDummyData
    { 
        string Msg { get; set; }
    }
}

IDummyData インターフェースは、親ウィンドウが複数ある場合に、共通のプロパティ (Msg) を利用して子ウィンドウからデータを受け渡すために使用されます。このインターフェースを導入することで、どの親ウィンドウとも一貫した方法でデータをやり取りできます。

親1ウィンドウ (Form1) のコード

using System;
using System.Windows.Forms;

namespace FormDataTrans
{
    public partial class Form1 : Form, IDummyData
    {
        public string Msg
        {
            get => label1.Text;
            set => label1.Text = value;
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            // 子ウィンドウをモーダルダイアログとして表示
            new Form2().ShowDialog(this);
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            // 別の親ウィンドウを生成
            new Form3().Show();
        }
    }
}

親2ウィンドウ (Form3) のコード

using System;
using System.Windows.Forms;

namespace FormDataTrans
{
    public partial class Form3 : Form, IDummyData
    {
        public string Msg
        {
            get => label1.Text;
            set => label1.Text = value;
        }

        public Form3()
        {
            InitializeComponent();
        }

        private void Button1_Click(object sender, EventArgs e)
        {
            // 子ウィンドウをモーダルダイアログとして表示
            new Form2().ShowDialog(this);
        }
    }
}

子ウィンドウ (Form2) のコード

using System;
using System.Windows.Forms;

namespace FormDataTrans
{
    public partial class Form2 : Form
    {
        private IDummyData parentForm;

        public Form2()
        {
            InitializeComponent();
        }

        private void Button2_Click(object sender, EventArgs e)
        {
            if (parentForm != null)
            {
                // 親ウィンドウのLabelにデータを渡す
                parentForm.Msg = "ボタンが押されました";
            }
        }

        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (parentForm != null)
            {
                // 親ウィンドウに子ウィンドウが閉じられたことを通知
                parentForm.Msg = "Form2が閉じられました";
            }
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            // 親ウィンドウのIDummyDataインターフェースを取得
            parentForm = Owner as IDummyData;
            if (parentForm == null)
            {
                MessageBox.Show("親ウィンドウが対応していません。");
                this.Close();
            }
        }
    }
}

この修正版では、Form2_Load メソッド内で parentForm の取得に失敗した場合(つまり Owner が IDummyData インターフェースを実装していない場合)にエラーメッセージを表示し、ウィンドウを閉じる処理を追加しました。これにより、実行時のエラーを防ぐことができます。

実行結果

親1(Form1)の場合

  1. Form1 の button1 をクリックすると、Form2 ウィンドウが作成されます。
  2. Form2 の button2 をクリックすると、Form1 の label1 の表示が「ボタンが押されました」に変わります。
  3. Form2 を閉じると、Form1 の label1 の表示が「Form2が閉じられました」に変わります。

親2(Form3)の場合

  1. Form3 の button1 をクリックすると、Form2 ウィンドウが作成されます。
  2. Form2 の button2 をクリックすると、Form3 の label1 の表示が「ボタンが押されました」に変わります。
  3. Form2 を閉じると、Form3 の label1 の表示が「Form2が閉じられました」に変わります。

まとめ

この技術資料では、親ウィンドウと子ウィンドウ間でのデータのやり取り方法を解説しました。単一の親と子の関係だけでなく、複数の親ウィンドウが存在する場合にも対応する方法を紹介しました。インターフェースを使用することで、ポリモーフィズムを活用し、コードの柔軟性と安全性を高めることができました。また、エラーハンドリングを追加することで、実行時の安定性も向上させています。