投稿者 魔界の仮面弁士  (社会人) 投稿日時 2023/11/27 16:04:32
CallByName や Controls(名前) による動的取得はパフォーマンスが悪いので、
何度も繰り返し呼び出すのであれば、事前に Dictionary や List などに、
対象のコントロール一覧をキャッシュしておいた方が良いですよ。
一回しか呼び出さないのであれば問題無いですけれども。

> 以下のような形で表示させたいのですができますでしょうか
今回のケースでは、
 Me.Controls("Panel1").Controls(AcName).Text
 DirectCast(CallByName(My.Forms, FrmName, CallType.Get), Form).Controls.Find(AcName)(0).Text
 DirectCast(CallByName(My.Forms, FrmName, CallType.Get), Form).Controls(”Panel1").Controls(AcName).Text 
といった感じでアクセスできるかと。

ただし、コントロール名に頼った実装は、画面構成が変化したときに、
呼び出す側に追加の改修が必要になってしまうというデメリットがあります。
名前文字列の指定が間違っていても、コンパイル時には検出できませんし、
パフォーマンスも落ちますので、あまり多用はしない方が良いでしょうね。


> With DirectCast(CallByName(My.Forms, FrmName, CallType.Get), Form)
>        MsgBox(.Panel1.Controls(AAA).Text) 'Panel1はFormのメンバーではありませんとなります。
> End With
Panel1 が Form1 のメンバーであるからといって、
Panel1 が Form のメンバーということにはなりません。

Me.Panel1 という書き方をした場合、この Panel1 フィールドは、
System.Windows.Forms.Form クラスのメンバーなのではなく、
それを継承した「エピさん独自の Form1 クラス」のメンバーです。

ですから、.Panel1 にアクセスさせたいのであれば、
DirectCast(~, Form) ではなく、
DirectCast(~, Form1) と書かねばなりません。

もし、複数のフォームで共通的に扱えるようにしたいというのであれば、
「対象となるフォームすべてに、Panel を返すメンバーがある状態」を保証する必要があります。

たとえば、Panel を返す共通のインターフェイスを作っておきます。
Interface IHoge
    ReadOnly Property ContainerPanel() As Panel 'Function でも可 
End Interface


次にこのインターフェイスを、各フォームに Implements します。
各フォームでは、この ContainerPanel プロパティを実装して、
「Return Me.Panel1」なり「Return Me.Panel2」なりを返すようにします。

あとは、今までエラーになっていた
 DirectCast(CallByName(……), Form).Panel1
の代わりに
 DirectCast(CallByName(……), IHoge).ContainerPanel
のように書けば OK です。


この方法は追加のインターフェイスが必要な分、一見面倒なようですが、
画面デザインの変更があったときに、呼び出し側の改修が不要になるというメリットがあります。

たとえば、Form1 と Form3 は Panel1 しかないのに対し、
Form2 だけは、選択している RadioButton によって、
表示するコンテナを Panel1 / Panel2 とで切り替えたい…という改修が入ったとします。

その場合、Form2 における ContainerPanel の実装を
 Return If(Radio1.Checked, Panel1, Panel2)
に変更するだけで済みます。呼び出し側のコードは
 DirectCast(CallByName(……), IHoge).ContainerPanel
のまま、何も変える必要がありません。


とはいえ、フォーム上のコントロールを、
フォーム外から直接読み書きしている時点で、
あまり望ましい実装とは言えないのですけれども。