連載:Windowsフォーム開発入門【Visual Studio 2010対応】
Windowsフォーム間連携の基礎 初音 玲2010/12/07 |
|
Page1
Page2
|
■子フォームに値を渡す方法
親フォームから子フォームに値を渡す方法はいろいろあるが、フォームがFormクラス(System.Windows.Window名前空間)を継承したクラスであることに気付けば、どのような方法で値を渡すのがよいのか見えてくる。
あるクラスをオブジェクト化して使う場合、そのオブジェクトに対する操作は「メソッド」または「プロパティ」を使う。通常、オブジェクト化されたクラス(=子オブジェクト)の中から、オブジェクト作成元のクラス(=親オブジェクト)の内容を直接参照するようなことはしないと思う。つまり、子オブジェクトが必要とする値は、親オブジェクトから渡してあげるのが、一般的な手法だ。これと同じことが、複数のWindowsフォーム間でもいえる。
親フォームから子フォームに値を渡すには、メソッドまたはプロパティを子フォームに追加する。親フォームから子フォームを表示する際に、そのメソッドやプロパティに渡したい値を設定すればよい。今回のサンプルでは、ShowメソッドとShowDialogメソッドを拡張することで、子フォームに値を渡してみたい。
リスト5では、Showメソッドにパラメータ「title」を1つ追加した(厳密には、Showメソッドをオーバーロードして、別バージョンのShowメソッドを作成した)。なお、このtitleパラメータは、フォーム・タイトルを指定するための文字列値を渡すためのものだ。
|
||
リスト5 Showメソッドにパラメータを追加したコード例(上:VB、下:C#) |
親フォームから子フォーム(=リスト5の例では、Method_Formクラスのオブジェクト)を生成して、そのShowメソッドのパラメータにタイトル(=文字列値)を指定して、拡張(=オーバーロード)したShowメソッドを呼び出す。これにより、リスト5のShowメソッドが呼び出される。
そのShowメソッド内では、まず、パラメータに渡された値をフォーム共通の変数(この例では「_title」)に設定している。
次に、Mybase.Showメソッド(C#の場合はbase.Showメソッド)を呼び出している。これによって、本来のShowメソッドの内容が実行され、フォームのLoadイベントやフォームのShownイベントが発生する。
先ほどフォーム共通変数に設定した値は、Shownイベントの中でフォームのタイトルに設定される。Loadイベントではなく、Shownイベントで設定しているのは、Showイベントはフォームが表示された直後に発生するが、Loadイベントは表示前に発生するため、Loadイベント・プロシージャに時間のかかる重たい処理を記述すると、処理が終わるまでフォームが表示されないからだ。よってLoadイベントでは、フォーム画面の表示内容をクリア(=初期化)するくらいの軽めの処理を記述する程度にとどめるのがよい(今回のようにタイトル設定くらいであればLoadイベントでも問題はない)。
時間のかかる処理を記述したのがShownイベントであれば、フォームが表示された後に処理が行われるため、エンド・ユーザーがフォームを表示する操作を行うとすぐにフォームが表示されてから処理待ちとなるため、操作に対する反応がよいUIが実現できる。
以上、Showメソッドの拡張例を説明した。ShowDialogメソッドも、ほぼ同様の実装が可能なので、説明は割愛する。
次の画面は、リスト5のプログラムを実行した例だ。[ShowDialogで値を渡す]ボタンや[Showで値を渡す]ボタンをクリックすると、子フォームが表示され、そのタイトルに(親フォームから渡された)文字列値(この例では「2010/11/11 1:36:41」)が設定される。
[Showで値を渡す]ボタン |
図2 子ウィンドウに値を渡す |
●拡張していない本来のメソッドを使わないようにするには
ShowメソッドやShowDialogメソッドを拡張して値を渡す場合、拡張していない本来のメソッドを使えないようにするか、コンストラクタなどで(その値の)デフォルト値を設定しておくのがよい。そのためにはObsolete属性(System名前空間)を使って、次のようなコードを書いてみるのもいいだろう。このコードでは、本来のShowDialogメソッドを、それと同じシグネチャ(=パラメータ群)を持つメソッドで(VBではOverloadsキーワード、C#ではnewキーワードにより)置き換えている。
|
||
リスト5 Obsolete属性の使用例(上:VB、下:C#) |
Obsolete属性を指定した形式のShowDialogメソッドを記述しようとしても、「旧形式」という判定でコンパイル・エラーとなり、コーディング時点で意図しない使用方法を除外できる。
図3 Obsolete属性によるコンパイル・エラー(上:VB、下:C#) |
■子フォームから値を取得する方法
子フォームに値を渡す場合は、ShowメソッドやShowDialogメソッドを拡張すればよい。しかし子フォームから値を取得したいときには、(ShowメソッドやShowDialogメソッドの戻り値では)値を1つだけしか返却できないため、使いづらい面がある。それを解決するのが独自プロパティの実装だ。
次のコードは、「Message」という独自プロパティを実装した子フォーム「Property_Form」のコード例である。
|
||
リスト7 子フォームに独自プロパティを記述した例(上:VB、下:C#) |
Messageプロパティは、自動プロパティ機能によりSetとGetが省略されている。親フォームからMessageプロパティに値を設定すると、内部的に値を保持して、その値をShownイベント・プロシージャの中でTextBoxコントロールに設定・表示している。
この独自プロパティを実装したWindowsフォーム・クラスを使って子フォームを表示するには、次のように記述する。
|
||
リスト8 独自プロパティを実装した子フォームを表示するコード例(上:VB、下:C#) |
ShowDialogメソッドを実行した親フォームは、子フォームが閉じられるまでは次の行に処理が移らない。よって、子フォームでMessageプロパティ値を変更してからフォームを閉じれば、「親フォームでそのMessageプロパティ値を取得して、子フォームでの操作結果を取得する」という流れが簡単に作れる。
■親フォームに値を設定する方法
先ほどのリスト8はShowDialogメソッドを使っていたので、メソッド実行後に子フォームのMessageプロパティを取得すれば、子フォームでの値の変更を取得できた。
もし、Showメソッドを使ったらどうだろうか。その場合、Showメソッドの実行は子フォームが表示されたらすぐに完了して次の行の処理を行うため、Showメソッドの次の行でMessageプロパティを参照しても、子フォーム側の値の変更と同期が取れない。
そこで、子フォームに独自イベントを追加し、子フォームでの値の変更が完了したところでイベントが発生するように拡張する必要が出てくる。
次のコードは、独自イベントを実装した子フォーム「Property_Form」のコード例である。
|
||
リスト9 フォームに独自イベントを記述した例(上:VB、下:C#) |
Visual BasicとC#で独自イベントの実装形式に多少の違いはあるが、今回のサンプルでは「FormCloseEvent」というイベントを新たに作成している。このイベントは第1パラメータとして自分自身のオブジェクトをイベント発生時に設定している。第2パラメータはほかのイベントと形を合わせるために定義しているが、イベント発生時には何も設定しない。
この独自イベントを実装したWindowsフォーム・クラスを使って子フォームを表示するには、次のように記述する。
|
||
リスト10 独自イベントを追加した子フォームを表示するコード例(上:VB、下:C#) |
イベントを使うためには、独自イベントに対するイベント・プロシージャを定義してイベントと関連付ける。今回はListジェネリック・クラスでフォームを管理しているので、「AddHandler」ステートメント(C#の場合は「+=」演算子)で動的にイベントと関連付けしてから、Listジェネリック・クラスに「Add」していくとよい。
これで子フォームを閉じれば、親フォームのイベント・プロシージャが自動的に呼び出される。そこで、子フォームの独自プロパティの値を参照すればよい。この手順により、Showメソッドを使った場合でも、子フォームから親フォームに値を返却できる。
■まとめ
複数フォーム間の情報共有は、「メイン・フォーム画面(=親フォーム)を表示したときに、自動的に認証用ログイン画面(=子フォーム)を開いて、そこで(エンド・ユーザーから)入力された認証情報をメイン画面で使う場合」など、特に業務アプリケーションを組むときに必要になってくる。しかし、Windowsフォーム・クラスには情報共有用のメンバが存在しないので、独自の対応が必要になる。
今回の記事では、ShowメソッドやShowDialogメソッドを拡張(=オーバーロード)して子フォームへの入力パラメータを実装し、独自プロパティにより出力パラメータを実装しているが、ほかにもいろいろ方法があると思う。もし、既存のコードに対して今回のサンプルで取り上げた方法を追加するのが難しいようであれば、情報共有のキーポイントは画面に配置したコントロール上の値を直接操作しないのが情報共有のキーポイントであるという点を踏まえたうえで、独自に実装するのもよいだろう。
INDEX | ||
[連載]Windowsフォーム開発入門【Visual Studio 2010対応】 | ||
Windowsフォーム間連携の基礎 | ||
1.Windowsフォーム表示の基本 | ||
2.子フォームに値を渡す方法/子フォームから値を取得する方法/親フォームに値を設定する方法 | ||
「Windowsフォーム開発入門」 |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
|
|
- - PR -