Windowsアプリケーションでは、メイン・フォームから別のフォーム(サブ・フォーム)を開き、サブ・フォームでの入力結果をメイン・フォームに反映するといった処理が必要になる場合がある。以下はこのような処理を行うサンプル・プログラムの実行画面である。
本稿ではこのような処理の基本的な実装方法についてまとめる。
サブ・フォームを扱ううえで、まずポイントとなるのは、サブ・フォームからメイン・フォームへの参照である。
メイン・フォーム内でサブ・フォームのインスタンスを作成するため、当然ながらメイン・フォームはサブ・フォームへの参照を持っているが、サブ・フォームからメイン・フォームのコントロールにアクセスするには、あらかじめメイン・フォームへの参照をサブ・フォームに渡しておかなければならない。
このような参照は、サブ・フォームを作成するときに呼び出すサブ・フォームのコンストラクタに、自分(=メイン・フォーム)への参照を引数として渡すようにすればよい。
なお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
一方、サブ・フォームのコンストラクタと、ボタンの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
また、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
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」「Form2」)と同じ名前でフォームにアクセスできる。
カテゴリ:Windowsフォーム 処理対象:フォーム
使用ライブラリ:WebBrowserコントロール(System.Windows.Forms名前空間)
使用ライブラリ:HtmlDocumentクラス(System.Windows.Forms名前空間)
関連TIPS:Windowsフォーム上のコントロールを検索するには?
Copyright© Digital Advantage Corp. All Rights Reserved.