投稿者 魔界の仮面弁士  (社会人) 投稿日時 2021/1/15 18:44:35
「Dim f2 As New Form2()」と「Form2」は別のインスタンスですし、
「Dim f3 As New Form2()」と「Form3」も別のインスタンスです。

Dim x As New Form2()
Dim y As New Form2()
x.Show(Me)
y.Show(Me)
を実行してみてください。Form2 が 2 つ開きますよね。
New することで、新たなフォーム インスタンスをいくつでも生成できるわけです。

ですから、Form3 で
 If Form2.CheckBox1.Checked = True Then
と書いても、これは x や y とは、まったく別の Form2 であることを意味します。
恐らく、この場合の Form2 上のコントロールの状態は、初期設定のままになっているはずです。

もし、Form2 のデザイン時に 、CheckBox1.Checked が False の状態であったのなら、
この If 文は満たさず、Else 句が実行されることになります。


> 親-子間ではできるのですが、子-孫間ではできないのはなぜなのでしょうか?
その「親」というのは、スタートアップ フォームに設定されているのではありませんか?
スタートアップ フォームは 自分で New して生成されたものでないため、
管理方法が異なるという事です。

New して生成されたフォームだとすれば、親子でも子孫でも同じ結果になりますし、
スタートアップフォームであっても、「Dim f1 As New Form1()」などとすれば、
それは「Form1」とは別のインスタンスということになります。

つまり「Form2.CheckBox1.Checked」のような書き方は、
暗黙のフォーム変数と呼ばれる書き方であり、
New Form2() で管理する方法とは共存できない、ということです。

また、New を使ってフォームを生成するかどうかによらず、
暗黙のフォーム変数は使わない方が望ましいです。


ではどうするかというと…方法はいくつかあります。


(方法1) Owner プロパティを使う

> f3.ShowDialog(Me)
で渡している Me こそが、本当に操作したい Form2 のインスタンスを表しているわけですから、
Form3 側で Me.Owner を取得すれば、ここから Form2 を得る事が可能というわけです。

ただし、Owner プロパティの型は As Form2 ではなく As Form ですから、
そこから CheckBox1 にアクセスするには、Form2 にキャストするか、
Me.Owner.Controls 経由で CheckBox1 にアクセスする必要があります。

この方法は、呼び出し元のフォームが Form2 である、ということを Form3 に
強制することになるため、他フォームから呼び出せるように改修したり、
画面遷移順の変更などに脆くなるため、保守性という点から、あまりお奨めしません。
フォーム関係の依存性が強くなりすぎます。

メッセージボックスに TextBox の内容を渡して表示させることはあっても、
メッセージボックス自体が TextBox の内容を読み取って表示することは
普通行われませんよね。

それと同じで、子が親を直接参照する設計は避けるべきです。