DOBON.NET DOBON.NETプログラミング掲示板過去ログ

フォーム名を動的に指定した場合の値の取得方法について

環境/言語:[Windows2000/SP4/VS.NET 2003/.NET Framework 1.1]
分類:[.NET]

参考書等を読みながら、VB.NETを勉強中ですが、どうも行き詰まってしまったので
投函させて頂きました。

親フォーム(frmA)から子フォーム(frmB)を呼び出す際
今まではフォーム名固定で次のように処理し、問題なく子フォームの値が
取得できていたのですが

親フォーム内の記述
Dim f As frmB
f = New frmB
f.ShowDialog()
Me.ActiveControl.Text = f.WinValue
※WinValueは子フォームにてPublic WinValue As Stringと宣言しています。

この部分の子フォーム名を動的にするため、次のように変更しました。

Dim pName As String = "WindowsApplication1"
Dim fName As String = "frmB"
Dim f As Form = DirectCast(Type.GetType(pName & "." & fName). _
GetConstructor(New Type() {}).Invoke(Nothing), Form)
f.ShowDialog()
Me.ActiveControl.Text = f.WinValue

この変更により、子フォームの変数WinValueへアクセスできなくなってしまい
困っております。
このようにフォーム名を動的にした場合、そのフォームからの値の取得は
どのように行えば良いのでしょうか?
どなたかご指導頂けると幸いです。

環境:Windows2000/SP4/VS.NET 2003/.NET Framework 1.1
言語:VB
形態:Windowsアプリ
> この変更により、子フォームの変数WinValueへアクセスできなくなってしまい
> 困っております。

案1) 子フォームに WinValueメンバを持ったInterfaceを実装させておき、
 DirectCast(f, インターフェイス).WinValue にてアクセスする。

案2) フォームのコンストラクタと同様、フォームのプロパティにも、
 FieldInfo.GetValue といったリフレクションにてアクセスする。

案3) Option Strict Off モードにした上で、CObj(f).WinValue でアクセスする。

案4) CallByName(f, "WinValue", CallType.Get) でアクセスする。
魔界の仮面弁士様、提案を4件も書いて頂きありがとうございます。
早速各案を調べて、案2.3.4にてうまく値を取得することができました。
案1については、私の勉強不足のため理解に苦しんでいます。
これについては今後じっくり勉強したいと思います。

本当にありがとうございました。


案2を採用しこんな感じになりました。
まず変数名を検索するクスラを作成。
これはここ↓を参考にしました。
http://dobon.net/vb/dotnet/control/findcontrolbyname.html

Public Shared Function FindControlByFieldName( _
ByVal frm As Form, ByVal name As String) As Object
Dim t As System.Type = frm.GetType()

'変数名検索
Dim fi As System.Reflection.FieldInfo = _
t.GetField(name, _
System.Reflection.BindingFlags.Public Or _
System.Reflection.BindingFlags.NonPublic Or _
System.Reflection.BindingFlags.Instance Or _
System.Reflection.BindingFlags.DeclaredOnly)

If fi Is Nothing Then
Return Nothing
End If

Return fi.GetValue(frm)
End Function

親フォームにて
Dim oForm As Form = _
DirectCast(Type.GetType(pName & "." & fName). _
GetConstructor(New Type() {}).Invoke(Nothing), Form)
oForm.ShowDialog()
Me.ActiveControl.Text = _
CType(FindControlByFieldName(oForm, "WinValue"), String)
解決済み!
> 早速各案を調べて、案2.3.4にてうまく値を取得することができました。
> 案1については、私の勉強不足のため理解に苦しんでいます。

案2はあまりお奨めできないです……。読みにくいし。(^_^;)

とりあえず、案1のサンプル。


手順1) 実装させるメンバを定義したインターフェイスを用意します。

  Public Interface ISayaForm
    ReadOnly Property WinValue() As String
  End Interface


手順2) 各子フォームに、それを実装させます。

Public Class 子フォーム
  Inherits System.Windows.Forms.Form
  Implements ISayaForm   '★
  Public ReadOnly Property WinValue() As String Implements ISayaForm.WinValue
    Get
      Return "〜戻り値〜"
    End Get
  End Property
End Class


これで完成です。呼び出し側は、
  Me.ActiveControl.Text = DirectCast(f, ISayaForm).WinValue
という感じですね。これなら、Option Strict On でも大丈夫です。


> Dim oForm As Form = _
>         DirectCast(Type.GetType(pName & "." & fName). _
>         GetConstructor(New Type() {}).Invoke(Nothing), Form)
> oForm.ShowDialog()
> Me.ActiveControl.Text = _
>         CType(FindControlByFieldName(oForm, "WinValue"), String)

最後の『oForm.Dispose()』が抜けていますよ。


なお案1 の場合、元のインターフェイスに、ShowDialog メソッドや
Dispose メソッドも実装しておけば、上記のコードを、
   Dim f As ISayaForm = DirectCast(〜〜.Invoke(Nothing), ISayaForm)
   f.ShowDialog()
   Me.ActiveControl.Text = f.WinValue
   f.Dispose()
のようにする事もできます。
魔界の仮面弁士様、サンプルまで書い頂いて申し訳ないです。
早速案2のところを案1に変更してみました。

標準モジュールを追加して次のようなインターフェイス定義を行いました。
Public Interface SubWinInterface
ReadOnly Property wValue() As String
Sub wShowDialog()
Sub wDispose()
End Interface

子フォームには次のコードを追加しました。
Implements SubWinInterface
Public ReadOnly Property wValue() As String Implements SubWinInterface.wValue
Get
Return "子フォームで選択した値"
End Get
End Property

Public Sub wShowDialog() Implements SubWinInterface.wShowDialog
Me.ShowDialog()
End Sub

Public Sub wDispose() Implements SubWinInterface.wDispose
Me.Dispose()
End Sub

親フォームには次のコードを追加しました。
Dim f As SubWinInterface = DirectCast(Type.GetType(pName & "." & fName). _
GetConstructor(New Type() {}).Invoke(Nothing), SubWinInterface)
f.wShowDialog()
Me.ActiveControl.Text = f.wValue
f.wDispose()

ShowDialog メソッドやDispose メソッドの実装は、問題なく動いていますが
この書き方で大丈夫なのかなぁと不安なところもあります。(^^;)
しかしながら、今回教えて頂いたインターフェイスの実装は大変勉強になりました!
機能を知っていても、どういう場面で使用すれば良いのかと迷う毎日ですが
いつかは回答する側になれることを夢見てがんばります!
ご指導ありがとうございました〜
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板