現実の世界では、多くの場合、フォームの新しいインスタンスを開くのではなく、既に情報が含まれている特定のインスタンスを開きたいと考えます。前回の記事では、ユーザーがラベルコントロールにロードしたテキストフレーズをFormクラスのインスタンスで表現する簡単な例を紹介しました。この基本的な実装のコードはリストAに示されています。では、既存のインスタンスを開く方法を見ていきましょう。それでは、C# .NETでFormクラスの特定のインスタンスを呼び出すための一般的なパターンを見ていきましょう。
C# フォームの復習が必要ですか?
概念が紹介され説明されているこの記事の最初の部分をご覧ください。
特定のフォームインスタンスの呼び出し
Form2インスタンスのボタンを使ってForm1インスタンスに戻りたいとします。ここで、Formクラスの新しいインスタンスを作成する際の制限にぶつかります。例として、Form2インスタンスのボタンのクリックイベントに対称的なコードを追加して、Form1インスタンスを表示します。
private void btnForm1_Click(object sender, System.EventArgs e) {
Form1 form1 = new Form1();
form1.Show();
}
図Aはコードの実行例です。次に、プロジェクトを起動します。Form1のテキストボックスに「私は考える、ゆえに私は存在する!」などのフレーズを入力します。ボタンをクリックしてラベルに読み込みます。次に、ボタンをクリックしてForm2のインスタンスを表示します。Form2でボタンをクリックして、Form1のインスタンスを表示します。これを何度繰り返しても、Form1の新しいインスタンスが作成されるだけです。つまり、ユーザーがラベルに読み込んだテキストは表示されません。
図A |
![]() |
もちろん、Windowsフォームのインスタンスには、ユーザーが入力したフレーズやその他の方法で収集された情報だけでなく、さらに多くの情報が含まれていることがよくあります。では、Form1の現在のインスタンスに戻り、その情報をそのまま保持するにはどうすればよいでしょうか?
当然のことながら、必要なのは、表示したいForm1の特定のインスタンスを指し示す、アクセス可能な変数です。これを実現する方法の一つは、インスタンスへの参照を保持するパブリックの静的変数を使用することです。(静的クラスメンバーと変数などのインスタンスクラスメンバーの違いは、静的メンバーはインスタンス化する必要がないことです。)
これを実現するには、Form1クラスの宣言のすぐ下に、Form1型のパブリックな静的変数を宣言します。この変数の名前はstaticVarとします。public
class Form1: System.Windows.Forms.Form
{
public static Form1 staticVar = null;
…
}
ちなみに、この変数をForm1モジュールに配置する必要はありません。publicかつstaticであれば、どこにでも配置できます。publicかつstaticな変数が複数ある場合は、専用のクラスモジュールを作成し、それら専用のクラスを作成することをお勧めします。また、変数をnullキーワードで初期化することで、フォームへの参照が明示的に含まれないようにしている点にも注意してください。
Form2 インスタンスを表示するときは、thisキーワードを使用して、現在の Form1 インスタンスへの参照をstaticVar変数に格納します
。staticVar = this;
Form2 のインスタンスを表示するクリック イベントの完全な修正コードは次のとおりです:
private void btnForm2_Click(object sender, System.EventArgs e) {
staticVar = this;
this.Hide();
Form2 form2 = new Form2();
form2.Show();
}
これで、 Form1.staticVar変数に保存された参照を使用するだけで、Form2 から Form1 の目的のインスタンスを簡単に開くことができます。修正した Form2 のクリックイベントは次のとおりです。private
void btnForm1_Click(object sender, System.EventArgs e) {
Form1.staticVar.Show();
}
プロジェクトを再度実行します。Form1のテキストボックスに「今度はインスタンスに戻ります!」などのテキストを入力します。ボタンをクリックしてForm1を非表示にし、Form2を表示します。Form2の「Form1を表示」ボタンをクリックすると、図Bに示すように、入力したForm1のインスタンスが表示されます。
図B |
![]() |
現状でも問題なく動作します。しかし、パブリック変数を多用することは、優れたプログラミングプラクティスの規範に違反しています(具体的には、変数がカプセル化されていない)。さらに、リソースを過度に消費する可能性もあります。もう少し良い解決策としては、フォームインスタンスへの参照をいずれかのクラスのプロパティとして保存する方法があります。
Form2 クラスに、Form クラスのインスタンスへの参照を格納するプロパティを追加してみましょう。(特定の Form1 クラスではなく、より一般的な Form クラスを使用してプロパティを作成していることに注意してください。そのため、Form1 インスタンスだけでなく、Form クラスから派生した任意のクラスのインスタンスへの参照をこのプロパティに格納できます。)
クラス ビュー ウィンドウからアクセスできる C# プロパティ ウィザードを使用すると、プロパティの作成をすぐに開始できますが、Form2 クラス モジュールで手動で作成するのも簡単です。
以下は、Form2 クラス モジュールに追加されたプロパティです (クラス本体のどこにでも配置できます)。
private Form m_InstanceRef = null;
public Form InstanceRef{
get {
return m_InstanceRef;
}
set {
m_InstanceRef = value;
} }
クラス インスタンス内に値を格納するためのプライベート変数、getおよびsetアクセサー、および新しいプロパティ値を設定するためのvalueキーワードの使用に注意してください。
次に、Form1 のクリックイベント(Form2 を呼び出す)を、パブリック変数ではなくプロパティを使用するように変更する必要があります。これを行うには、this(現在のフォームインスタンス)への参照をプロパティに代入します。
private void btnForm2_Click(object sender, System.EventArgs e) {
this.Hide();
Form2 form2 = new Form2();
form2.InstanceRef = this;
form2.Show();
}
最後に、Form2でこのプロパティを使用して、Form1の適切なインスタンスを呼び出します(図C)。このプロパティは現在のインスタンスのメンバーであるため、プロパティの前に修飾子を付ける必要はありません。private
void btnForm1_Click(object sender, System.EventArgs e) {
InstanceRef.Show();
}
図C |
![]() |
ご覧のとおり、プロパティは Windows フォーム アプリケーション内のさまざまなモジュール間でフォーム インスタンスを通信するのに適しており、パブリックの静的変数を使用するよりもカプセル化されたアプローチを提供します。
フォームの基盤
この2部構成の記事では、C#におけるWindowsフォームの相互運用性に関する主要なパターンについて説明しましたが、実際に作業を進めていくと、プロジェクトの特定のニーズに応じた細かな点に気付くでしょう。例えば、配列やコレクションなどの構造体が複数のフォームを指す場合、構造体内で参照されている様々なインスタンスから適切な参照を選択する必要があるでしょう。しかし、ここで紹介した一般的なアプローチは、良いスタートを切るのに役立つはずです。