連載
» 2008年06月12日 05時00分 公開

.NET TIPS:サブ・フォームからメイン・フォームのコントロールに値を設定するには?[C#、VB]

[遠藤孝信,デジタルアドバンテージ]
「.NET TIPS」のインデックス

連載目次

 Windowsアプリケーションでは、メイン・フォームから別のフォーム(サブ・フォーム)を開き、サブ・フォームでの入力結果をメイン・フォームに反映するといった処理が必要になる場合がある。以下はこのような処理を行うサンプル・プログラムの実行画面である。

[Form2を開く]ボタンをクリック
[Form2を開く]ボタンをクリック
文字を入力して[Form1に渡す]ボタンをクリック
文字を入力して[Form1に渡す]ボタンをクリック
2つのフォームを使用したサンプル・プログラムの実行画面 2つのフォームを使用したサンプル・プログラムの実行画面
サブ・フォームで入力した文字列がメイン・フォームのラベルに表示される。

 本稿ではこのような処理の基本的な実装方法についてまとめる。

サブ・フォームからメイン・フォームへの参照

 サブ・フォームを扱ううえで、まずポイントとなるのは、サブ・フォームからメイン・フォームへの参照である。

 メイン・フォーム内でサブ・フォームのインスタンスを作成するため、当然ながらメイン・フォームはサブ・フォームへの参照を持っているが、サブ・フォームからメイン・フォームのコントロールにアクセスするには、あらかじめメイン・フォームへの参照をサブ・フォームに渡しておかなければならない。

サブ・フォームからメイン・フォームへの参照 サブ・フォームからメイン・フォームへの参照

 このような参照は、サブ・フォームを作成するときに呼び出すサブ・フォームのコンストラクタに、自分(=メイン・フォーム)への参照を引数として渡すようにすればよい。

 なおVisual Basic 2005以降では、「既定のインスタンス」と呼ばれる機能があり、これを使えばサブ・フォームの明示的なインスタンス化(Newの実行)や、メイン・フォームへの参照の受け渡しは不要となる。

メイン・フォーム上のコントロールへのアクセス

 もう1つのポイントとなるのが、メイン・フォーム上に配置されているコントロールへのアクセス方法であるが、これは「TIPS:Windowsフォーム上のコントロールを検索するには?」で解説している方法により、メイン・フォームのControlsプロパティから可能だ。

 あるいはフォームのデザイン時に、対象となっているコントロールのModifiersプロパティを、「private」から「internal」に(VBの場合には「Private」から「Friend」に)変更する。このようにすれば、コントロールへの参照がセットされているメイン・フォームのフィールドに直接外部からアクセスすることができる。

 Modifiersプロパティは、自動生成されるコード内のフィールドの宣言に使用されるアクセス修飾子を指定するためのもので、これがinternal/Friendであれば、同じアセンブリの別のクラスからでもアクセス可能となる。

 なお、サブ・フォームからのアクセス用に、メイン・フォームのクラスにコントロール値設定用のプロパティを追加するという方法もよく利用される。これによりメイン・フォームでの具体的な実装もカプセル化できるが、上記の2つの方法と比べると若干手間がかかる。

サンプル・プログラムの作成

 以上の方法を実装したサンプル・プログラムを次に示す。実行時の動作は冒頭で示したとおりだ。

 まずは冒頭の最初の画面のように、メイン・フォームにはLabelコントロールとButtonコントロールを配置する。次に、プロジェクトにサブ・フォームとなるWindowsフォームを追加し、こちらにはTextBoxコントロールとButtonコントロールを配置する。

 そしてメイン・フォームのボタンをダブルクリックし、次のようなClickイベント・ハンドラを記述する。Clickイベント・ハンドラ内では、this/Meはメイン・フォームのインスタンスを参照している。

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
  public partial class Form1 : Form
  {
    public Form1()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      Form2 f2 = new Form2(this); // 自フォームへの参照を渡す
      f2.Show(); // サブ・フォームを表示
    }
  }
}

Public Class Form1

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim f2 As New Form2(Me) ' 自フォームへの参照を渡す
    f2.Show() ' サブ・フォームを表示
  End Sub
End Class

メイン・フォームのコード(上:C#、下:VB)
サブ・フォームのインスタンスを作成し、それをShowメソッドにより表示する。

 一方、サブ・フォームのコンストラクタと、ボタンのClickイベント・ハンドラは次のようになる。

using System;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
  public partial class Form2 : Form
  {
    Form1 f1;

    // コンストラクタ
    public Form2(Form1 f)
    {
      f1 = f; // メイン・フォームへの参照を保存
      InitializeComponent();
    }

    // ボタンのClickイベント・ハンドラ
    private void button1_Click(object sender, EventArgs e)
    {
      Label f1_label1 = (Label)f1.Controls["label1"];
      f1_label1.Text = this.textBox1.Text;

      // メイン・フォームのラベルのModifiersプロパティを
      // internalにした場合は次の1行でOK
      //
      // f1.label1.Text = this.textBox1.Text;
    }
  }
}

Public Class Form2

  Dim f1 As Form1

  ' コンストラクタ
  Sub New(ByVal f As Form)
    f1 = f ' メイン・フォームへの参照を保存
    InitializeComponent()
  End Sub

  ' ボタンのClickイベント・ハンドラ
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim f1_label1 As Label = CType(f1.Controls("Label1"), Label)
    f1_label1.Text = Me.TextBox1.Text

    ' メイン・フォームのラベルのModifiersプロパティを
    ' Friendにした場合は次の1行でOK
    '
    'f1.Label1.Text = Me.TextBox1.Text
  End Sub
End Class

サブ・フォームのコード(上:C#、下:VB)
コンストラクタで受け取ったメイン・フォームへの参照を使用して、メイン・フォーム上のラベルにテキストボックスで入力された文字列をセットする。

 また、VBで「既定のインスタンス」を利用した場合には、2つのフォームのコードは次のように非常にシンプルになる。サブ・フォームを作成したり、サブ・フォームにメイン・フォームの参照を渡したりする必要はない。

Public Class Form1

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Form2.Show() ' サブ・フォームを表示
  End Sub
End Class

メイン・フォームのコード(既定のインスタンス使用時)
「Form2」がサブ・フォームの既定のインスタンスを参照している。

Public Class Form2

  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim f1_label1 As Label = CType(Form1.Controls("Label1"), Label)
    f1_label1.Text = Me.TextBox1.Text
  End Sub
End Class

サブ・フォームのコード(既定のインスタンス使用時)
「Form1」がメイン・フォームの既定のインスタンスを参照している。

 「既定のインスタンス」では、フォームのクラス名(本稿の場合には「Form1」「Form2」)と同じ名前でフォームにアクセスできる。

カテゴリ:Windowsフォーム 処理対象:フォーム
使用ライブラリ:WebBrowserコントロール(System.Windows.Forms名前空間)
使用ライブラリ:HtmlDocumentクラス(System.Windows.Forms名前空間)
関連TIPS:Windowsフォーム上のコントロールを検索するには?


「.NET TIPS」のインデックス

.NET TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。