C#/WinForms 別フォームのチェックボックス状態を取得する方法(プロパティ設計と「親子フォーム」の誤解)

広告

WinFormsでアプリを作っていると、「別のフォームにあるコントロールの状態を、こちらのフォームで使いたい」という場面によく出会います。

たとえば次のようなケースです。

  • Form1にラベルとボタンがある
  • Form2にはチェックボックスがある
  • Form2はForm1が生成されるときに一緒に作られる
  • Form1のボタンを押すと、Form2のチェックボックスの状態をForm1のラベルに表示したい

一見シンプルですが、「別フォームのprivateなコントロールに、どうやって安全にアクセスするか」という設計の基本が詰まっています。今回はこの実装を、順を追って解説します。

全体の構成

Form1にlabel1(結果を表示するラベル)とbutton1(押すとForm2の状態を取得するボタン)があり、Form1生成時に同時に作成・保持されるForm2の中にcheckBox1があります。

ポイントは「Form2の内部にあるcheckBox1そのもの」をForm1から直接触るのではなく、Form2側に状態を公開するための窓口(プロパティ)を用意することです。

補足:「親子」という言葉について
WinFormsで「親子フォーム」というと、IsMdiContainer = trueにしたフォームとMdiParentを設定したフォームからなる、MDI(Multiple Document Interface)の親子関係を指すのが一般的です。今回のようにForm1がForm2をnewして保持しているだけの関係は、MDIの親子とは異なります。単に「一方のフォームが、もう一方のインスタンスを持っている」だけの通常のオブジェクト参照です。

もし「Form1を閉じたらForm2も閉じる」「Form1の手前に表示され続ける」といった見た目上の親子関係を持たせたい場合は、form2.Show(this)のようにOwnerを指定する方法があります(Ownedフォーム)。これもMDIの親子とは別の仕組みです。

Form2側:状態を公開するプロパティを作る

checkBox1はデザイナーが自動生成したprivateなフィールドです。これを直接publicに変更することもできなくはないのですが、コントロールそのものを外部に晒してしまうと、Form1側から意図せずチェックボックスのプロパティを書き換えられたり、テキストを変更されたりするリスクが生まれます。

そこでIsCheckedという読み取り専用プロパティ(getアクセサのみの式形式プロパティ)を用意し、「チェック状態というデータだけ」を外に見せるようにします。これはオブジェクト指向の基本であるカプセル化の考え方です。

Form1側:Form2を生成して保持する

ここでの設計上のポイントは2つです。

①form2をフィールドとして保持する
コンストラクタのローカル変数としてForm2を作ってしまうと、コンストラクタの処理が終わった時点でその変数は参照できなくなります。あとからbutton1_Clickなどのイベントハンドラー内で使えるように、クラスのフィールド(メンバ変数)として保持しておく必要があります。

②form2.Show()は任意
Form2を実際に画面に表示したいのか、裏側でデータだけ持たせておきたいのかによって変わります。表示せず内部的にだけ使いたい場合はform2 = new Form2();の行だけで構いません(インスタンスは生成されますが画面には表示されません)。

ボタンクリック時の処理

form2.IsCheckedはbool型の値なので、三項演算子(条件 ? Aの場合の値 : Bの場合の値)を使って、表示する文字列を切り替えます。

まとめ

やりたいこと実装方法
別フォームの状態を安全に取得したい対象フォームに読み取り専用プロパティを用意する
生成したフォームをあとから使いたいインスタンスをフィールドに保持する
ボタン操作で他フォームの状態を反映したいイベントハンドラー内でプロパティを参照する

WinFormsでは複数のフォームを組み合わせてアプリを作ることが多いため、「フォームをまたいで値を受け渡す」パターンは非常によく登場します。今回のようにプロパティを窓口にする方法を覚えておくと、コントロールをむやみにpublicにすることなく、安全にフォーム間の連携ができるようになります。

なお、「親子フォーム」という言葉はMDIの文脈で使われる用語のため、単に一方のフォームが他方を生成・保持しているだけの関係を指すときは、「生成元・生成先」「呼び出し元・呼び出し先」といった表現を使うほうが誤解がありません。

訪問数 3 回, 今日の訪問数 3回

広告