DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

別のフォームのデータを取得、設定する

ここでは、例えば2つのフォームForm1とForm2があり、Form1からForm2のデータ(例えば、TextBoxに入力されている値)を取得したい(あるいは設定したい)時にどのようにすればよいかについて説明します。

注意:もしForm2が一つしか表示されなくて良いのであれば、「フォームが一つしか表示されないようにする」で紹介している方法を使うのが最も簡単です。そのような場合は、まずはそちらをご覧いただき、その方法では解決できなければ、この記事を参考にしてください。

まず初めにお断りしておきたいのは、状況により最適な方法は異なり、すべてのケースに対応できる適切な方法はないということです。ここでは性急な読者のために初めに「汎用的な方法」を紹介していますが、できるだけこのページを最後までお読みいただき、状況に応じた適切なコードを書けるようになっていただきたいと希望します。

汎用的な方法

まずはどのような状況でも使えるであろう汎用的な方法を紹介します。あくまで汎用的な方法であり、すべての状況に適した方法ではありません(この方法が最適というケースはあまりないでしょう)。ここでは具体的に、フォーム"Form1"にテキストボックス"TextBox1"が配置されており、TextBox1.Textプロパティの値を別のフォーム(クラス)から取得、設定できるようにします。

1.Form1クラスにForm1型のプライベートな静的フィールドとパブリックな静的プロパティを作成します。(Form1を複数開く場合は、その数だけフィールドとプロパティを作成するか、Form1配列(あるいはコレクション)型のフィールドとプロパティを作成してください。)

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//Form1オブジェクトを保持するためのフィールド
private static Form1 _form1Instance;

//Form1オブジェクトを取得、設定するためのプロパティ
public static Form1 Form1Instance
{
    get
    {
        return _form1Instance;
    }
    set
    {
        _form1Instance = value;
    }
}

2.TextBox1.Textプロパティの値を取得、設定するためのパブリックなプロパティをForm1クラスに作成します。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//TextBox1.Textを取得、設定するためのプロパティ
public string TextBoxText
{
    get
    {
        return TextBox1.Text;
    }
    set
    {
        TextBox1.Text = value;
    }
}

3.Form1クラスのインスタンスを作成した時に、そのForm1クラスのインスタンスを先ほど作成した静的プロパティに代入します。

VB.NET
コードを隠すコードを選択
'Form1のインスタンスの作成
Dim f As New Form1
'Form1Instanceに代入
Form1.Form1Instance = f
'Form1の表示
f.Show()
C#
コードを隠すコードを選択
//Form1のインスタンスの作成
Form1 f = new Form1();
//Form1Instanceに代入
Form1.Form1Instance = f;
//Form1の表示
f.Show();

VB.NETのメインフォームのようにコードでインスタンスを作成しない場合は、フォームのLoadイベントハンドラで代入してください。

VB.NET
コードを隠すコードを選択
'Form1のLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles MyBase.Load
    Form1.Form1Instance = Me
End Sub
C#
コードを隠すコードを選択
//Form1のLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    Form1.Form1Instance = this;
}

以上で準備は完了しました。TextBox1.Textプロパティの値を別のフォームから取得または設定するには、次のようにForm1Instanceプロパティにアクセスします。(Form1と異なる名前空間から呼び出すときは、適切な名前空間名を付加してください。)

VB.NET
コードを隠すコードを選択
'Form1のTextBox1.Textの値を取得
Dim str As String = Form1.Form1Instance.TextBoxText

'Form1のTextBox1.Textの値を設定
Form1.Form1Instance.TextBoxText = "こんにちは。"
C#
コードを隠すコードを選択
//Form1のTextBox1.Textの値を取得
string str = Form1.Form1Instance.TextBoxText;

//Form1のTextBox1.Textの値を設定
Form1.Form1Instance.TextBoxText = "こんにちは。";

基本的な考え方

ここからはケースバイケースで最適な方法を選択できるようになるための基本的な考え方について述べます。

「どのように別のフォームのデータにアクセスするか?」という問題は、次の2点に集約され、結局はこの2つをどのように解決するかという問題だといえます。

  1. どのようにデータをフォームクラスの外部に公開するか?
  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を次のように開きます。

VB.NET
コードを隠すコードを選択
Dim f As New Form2
f.ShowDialog(Me)
f.Dispose()
C#
コードを隠すコードを選択
Form2 f = new Form2();
f.ShowDialog(this);
f.Dispose();

この様にして開かれたForm2からForm1のTextBoxTextプロパティにアクセスするには、次のようにします。

VB.NET
コードを隠すコードを選択
'Form1のTextBox1.Textの値を取得
Dim str As String = CType(Me.Owner, Form1).TextBoxText

'Form1のTextBox1.Textの値を設定
CType(Me.Owner, Form1).TextBoxText = "こんにちは。"
C#
コードを隠すコードを選択
//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プロパティにアクセスしています。

VB.NET
コードを隠すコードを選択
'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
C#
コードを隠すコードを選択
//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つである場合は、「フォームが一つしか表示されないようにする」も参考にしてください。

最後に

ここで紹介した方法以外にもいろいろな方法があると思いますが、今後経験を積み知識が増えれば、これらの解説がかえってわずらわしく感じることでしょう。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。