C#の場合はVB.NETと異なる
C#でマルチフォーム(フォームが複数有る)プログラムを作成した場合、
それぞれのフォームのコントロールに相互にアクセスしたい場合が有る。
ただしそれぞれのフォームのコントロールはマルチスレッド同様にプロテクトされており、
他のフォームから其のコントロールにアクセスすることは禁止されている。
そこで考えられるのは、各々のフォームでグローバルにコントロールの操作の
メソドを作っておいて、其のメソドに別のフォームからアクセスする方法である。
別のフォームのメソドにアクセスする場合は其のフォームのインスタンスを知らなくてはならない。
下のプログラムは、Form1がForm2のインスタンスを作成している例である。
作成側のForm1(正確にはForm1のインスタンス)はForm2のインスタンスを知っているので、
其のインスタンスからForm2のインスタンスのメソドを呼び出せばよいわけである。
Form2のインスタンスには、Form1がForm2のインスタンスを作成する時に、コンストラクタを
の引数としてForm1のインスタンス(this)を渡す。
Form2(正確にはForm2)のインスタンスは渡されたForm1のインスタンスを使って、其のメソドに
アクセスすれば良いことになる。
C# Form1側のコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace form1toform2
{
public partial class Form1 : Form
{
// Form2の宣言
Form2 f2;
public Form1()
{
InitializeComponent();
//Form2にインスタンスを作成してForm1のインスタンスを渡す
f2 = new Form2(this);
//Form2のインスタンスの表示
f2.Show();
}
//Form2から呼ばれる関数
public void setText(string text)
{
textBox1.Text = text;
}
//Form2の関数を呼び出す
private void button1_Click(object sender, EventArgs e)
{
f2.setText(textBox1.Text);
}
}
}
C# Form2側のコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace form1toform2
{
public partial class Form2 : Form
{
//Form1の宣言
Form1 f1;
//コンストラクタにForm1のインスタンスが渡ってくる
public Form2(Form1 _f1)
{
InitializeComponent();
//Form1のインスタンスを代入
f1 = _f1;
}
//Form1から呼び出される関数
public void setText(string text)
{
textBox1.Text = text;
}
//Form1の関数を呼び出す
private void button1_Click(object sender, EventArgs e)
{
f1.setText(textBox1.Text);
}
}
}
C# 書き込み実行時にForm2のインスタンスを作成する方法
上の方法はForm1の表示と共にForm2が表示されるが、書き込み時又は任意の時に
Form2を表示するにはどうしたら良いのだろうか?
以下に其のコードを示す、 if (f2 == null)でインスタンスが既に有るか否かを
判断してなければ作成、表示して、既にあれば作成しなければ良いので有る。
C# 書き込み実行時にForm2のインスタンスそ作成する方法 Form1側のコード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace form1toform2
{
public partial class Form1 : Form
{
// Form2の宣言
Form2 f2;
public Form1()
{
InitializeComponent();
}
//Form2から呼ばれる関数
public void setText(string text)
{
textBox1.Text = text;
}
//Form2の関数を呼び出す
private void button1_Click(object sender, EventArgs e)
{
//Form2のインスタンスが出来ていなければ作る
if (f2 == null)
{
//Form2にインスタンスを作成してForm1のインスタンスを渡す
f2 = new Form2(this);
//Form2のインスタンスの表示
f2.Show();
}
f2.setText(textBox1.Text);
}
}
}
VB2005で Form1、Form2の相互参照
問題はVB2005である、VB2005は「デフォルトインスタンスとの会話」という方法が取られる。
Form1、Form2は型で有ると同時にインスタンス名なのだ。
従って 、 Form2.Show()これだけでForm2が表示され、しかもForm2のコントロールに全てアクセス可能なのだ。
これに関してはVB2005になってから大きく言語の仕様が変更された。
VB2005以前のバージョンをお使いの方は 「VB.NET Form1、Form2の相互参照 」 を参照して下さい。
注意点は、Form1の中ではForm1で自分のインスタンスを呼び出せない、自分のインスタンスはあくまでも 「Me」である。
なおこの変更に関しては改悪で有ると言う意見もあるが、デフォルトインスタンスを使わない方法も有るので目くじらを立てることも無い。
ただしC#とVB2005の違いは、VB2005は別のフォームのインスタンスから他のフォームのインスタンスのコントロールに自由に
アクセス出来る点で、この為他のコントロールから自分のコントロールを操作するメソドは不要である。
VB2005 Form1側のコード
Option Strict On
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Form2.Show()
End Sub
Private Sub Button1_Click_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Form2.TextBox1.Text = Me.TextBox1.Text
End Sub
End Class
VB2005 Form2側のコード
Public Class Form2
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Form1.TextBox1.Text = Me.TextBox1.Text
End Sub
End Class
VB2005のデフォルトインスタンスを使用しないコード
VB2005でももちろんC#と同様にデフォルトインスタンスを使用しないで、Form2のコンストラクタに
Form1のインスタンスを渡す方法もある。
Form1側のコード
Option Strict On
Public Class Form1
Private F2 As Form2
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
F2 = New Form2(Me)
F2.Show()
End Sub
Private Sub Button1_Click_1(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
F2.TextBox1.Text = Me.TextBox1.Text
End Sub
End Class
Form2側のコード
Public Class Form2
Dim F1 As Form1
Public Sub New(ByVal fomForm1 As Form1)
InitializeComponent() 'これは必ず必要です
F1 = fomForm1
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
F1.TextBox1.Text = Me.TextBox1.Text
End Sub
End Class
|