ここでは、例えば2つのフォームForm1とForm2があり、Form1からForm2のデータ(例えば、TextBoxに入力されている値)を取得したい(あるいは設定したい)時にどのようにすればよいかについて説明します。
注意:もしForm2が一つしか表示されなくて良いのであれば、「フォームが一つしか表示されないようにする」で紹介している方法を使うのが最も簡単です。そのような場合は、まずはそちらをご覧いただき、その方法では解決できなければ、この記事を参考にしてください。
まず初めにお断りしておきたいのは、状況により最適な方法は異なり、すべてのケースに対応できる適切な方法はないということです。ここでは性急な読者のために初めに「汎用的な方法」を紹介していますが、できるだけこのページを最後までお読みいただき、状況に応じた適切なコードを書けるようになっていただきたいと希望します。
まずはどのような状況でも使えるであろう汎用的な方法を紹介します。あくまで汎用的な方法であり、すべての状況に適した方法ではありません(この方法が最適というケースはあまりないでしょう)。ここでは具体的に、フォーム"Form1"にテキストボックス"TextBox1"が配置されており、TextBox1.Textプロパティの値を別のフォーム(クラス)から取得、設定できるようにします。
1.Form1クラスにForm1型のプライベートな静的フィールドとパブリックな静的プロパティを作成します。(Form1を複数開く場合は、その数だけフィールドとプロパティを作成するか、Form1配列(あるいはコレクション)型のフィールドとプロパティを作成してください。)
'Form1オブジェクトを保持するためのフィールド Private Shared _form1Instance As Form1 'Form1オブジェクトを取得、設定するためのプロパティ Public Shared Property Form1Instance() As Form1 Get Return _form1Instance End Get Set(ByVal Value As Form1) _form1Instance = Value End Set End Property
//Form1オブジェクトを保持するためのフィールド private static Form1 _form1Instance; //Form1オブジェクトを取得、設定するためのプロパティ public static Form1 Form1Instance { get { return _form1Instance; } set { _form1Instance = value; } }
2.TextBox1.Textプロパティの値を取得、設定するためのパブリックなプロパティをForm1クラスに作成します。
'TextBox1.Textを取得、設定するためのプロパティ Public Property TextBoxText() As String Get Return TextBox1.Text End Get Set(ByVal Value As String) TextBox1.Text = value End Set End Property
//TextBox1.Textを取得、設定するためのプロパティ public string TextBoxText { get { return TextBox1.Text; } set { TextBox1.Text = value; } }
3.Form1クラスのインスタンスを作成した時に、そのForm1クラスのインスタンスを先ほど作成した静的プロパティに代入します。
'Form1のインスタンスの作成 Dim f As New Form1 'Form1Instanceに代入 Form1.Form1Instance = f 'Form1の表示 f.Show()
//Form1のインスタンスの作成 Form1 f = new Form1(); //Form1Instanceに代入 Form1.Form1Instance = f; //Form1の表示 f.Show();
VB.NETのメインフォームのようにコードでインスタンスを作成しない場合は、フォームのLoadイベントハンドラで代入してください。
'Form1のLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load Form1.Form1Instance = Me End Sub
//Form1のLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { Form1.Form1Instance = this; }
以上で準備は完了しました。TextBox1.Textプロパティの値を別のフォームから取得または設定するには、次のようにForm1Instanceプロパティにアクセスします。(Form1と異なる名前空間から呼び出すときは、適切な名前空間名を付加してください。)
'Form1のTextBox1.Textの値を取得 Dim str As String = Form1.Form1Instance.TextBoxText 'Form1のTextBox1.Textの値を設定 Form1.Form1Instance.TextBoxText = "こんにちは。"
//Form1のTextBox1.Textの値を取得 string str = Form1.Form1Instance.TextBoxText; //Form1のTextBox1.Textの値を設定 Form1.Form1Instance.TextBoxText = "こんにちは。";
ここからはケースバイケースで最適な方法を選択できるようになるための基本的な考え方について述べます。
「どのように別のフォームのデータにアクセスするか?」という問題は、次の2点に集約され、結局はこの2つをどのように解決するかという問題だといえます。
1.は簡単で、「汎用的な方法」の2.のように、データにアクセスするためのプロパティをフォームクラスに作成し、Publicとして公開すればよいのです。(もちろんPublicでなくても結構です。詳しくは「public、protected、internal、private、protected internalの違い」をご覧ください。)
難しいのは2.の方です。以降、対象となるフォームのインスタンスの取得法をケースごとに幾つか紹介します。なお以下の例では「汎用的な方法」と同様に、データを取得、設定するフォームにTextBoxTextプロパティが用意されているものとします。
Form2がForm1に所有されていれば、Form2からForm1はOwnerプロパティで取得できます。Form1からForm2を「f2.ShowDialog(this);」(C#)または「f2.ShowDialog(Me)」(VB.NET)のように表示させた場合がこのケースに当たります。モードレスの場合でも、「モードレスのフォームが、あるフォームの背後に隠れないようにする」のように所有を設定することができます。
Form1からForm2を開き、Form1からForm2のTextBoxTextプロパティにアクセスする例を次に示します。まずForm1からForm2を次のように開きます。
Dim f As New Form2 f.ShowDialog(Me) f.Dispose()
Form2 f = new Form2(); f.ShowDialog(this); f.Dispose();
この様にして開かれたForm2からForm1のTextBoxTextプロパティにアクセスするには、次のようにします。
'Form1のTextBox1.Textの値を取得 Dim str As String = CType(Me.Owner, Form1).TextBoxText 'Form1のTextBox1.Textの値を設定 CType(Me.Owner, Form1).TextBoxText = "こんにちは。"
//Form1のTextBox1.Textの値を取得 string str = ((Form1) this.Owner).TextBoxText; //Form1のTextBox1.Textの値を設定 ((Form1) this.Owner).TextBoxText = "こんにちは。";
例えば、Form2を作成したフォームからForm2を取得する場合は、Form2をフィールドに代入しておき、このフィールドからForm2を取得すればよいでしょう。
次に例を示します。ここではForm1のLoadイベントハンドラでForm2を開き、Button1のClickイベントハンドラでForm2のTextBoxTextプロパティにアクセスしています。
'Form2のインスタンスを格納しておくフィールド Private form2Instance As Form2 'フォームのLoadイベントハンドラ Private Sub Form1_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Form2のインスタンスをform2Instanceに代入 Me.form2Instance = New Form2 'Form2を表示 Me.form2Instance.Show() End Sub 'Button1のClickイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click 'Form2のTextBox1.Textの値を取得 Dim str As String = Me.form2Instance.TextBoxText 'Form2のTextBox1.Textの値を設定 Me.form2Instance.TextBoxText = "こんにちは。" End Sub
//Form2のインスタンスを格納しておくフィールド private Form2 form2Instance; //フォームのLoadイベントハンドラ private void Form1_Load(object sender, System.EventArgs e) { //Form2のインスタンスをform2Instanceに代入 this.form2Instance = new Form2(); //Form2を表示 this.form2Instance.Show(); } //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { //Form2のTextBox1.Textの値を取得 string str = this.form2Instance.TextBoxText; //Form2のTextBox1.Textの値を設定 this.form2Instance.TextBoxText = "こんにちは。"; }
これは、「汎用的な方法」で説明した方法です。フォームが必ず1つである場合は、「フォームが一つしか表示されないようにする」も参考にしてください。
ここで紹介した方法以外にもいろいろな方法があると思いますが、今後経験を積み知識が増えれば、これらの解説がかえってわずらわしく感じることでしょう。