- PR -

C#: MDI子フォームから親フォームへのアクセス方法

1
投稿者投稿内容
会議室デビュー日: 2004/11/14
投稿数: 14
投稿日時: 2005-02-24 11:11
MDI形式のWindowsアプリケーションについての質問です。
どうにも実現手法が見出せずにいます。
根本的なところが分かっていないからだと思います。
ご助言を頂けたら幸いです。VC# 2003 です。

[状況説明]
(1)親フォーム(FormParent)と子フォーム(FormChild)があります。
(2)親フォームには ToolBar や StatusBar があります。
(3)親フォームは本アプリEXEを作るプロジェクトに属し、
 子フォームはDLLプロジェクトに属します。
 親フォーム側のプロジェクトでは、
 子フォーム側のプロジェクトを参照設定にて加えています。

 ※DLLに分けている理由は以下のとおりです。
  ・子フォームが数種あり、いずれも(表現が悪いかもしれませんが)
   “孫フォーム”に相当する基底クラスがあり、
   フォーム継承によって出来上がっています。
  ・基底クラス(上の“孫フォーム”)はDLLに分けないと、
   フォーム継承が出来ないとの認識です。
  ・さらにそこから派生させた数種の子フォームも、
   他のアプリでの利用を将来的に考えてDLLとしました。

[やりたいこと]
・子フォームが開いた後、子フォーム内のユーザアクションや処理
 に応じて、親フォームの ToolBar や StatusBar にアクセスしたい。

 ToolBar については、例えば特定ボタンの Pushed 状態を変更する
 ものです。
 StatusBar については、子フォーム上での処理に応じて、
 単純に何らかのテキスト表示を行うものです。

[実現できずに困っていること]
・一言でいいますと、子フォーム上のコードにて、親フォームを
 認識できない点です。
 状況説明(3)のような、親子を2つの(別々の)プロジェクトに分ける
 ことを止めて(フォーム継承もとりあえずなしにして)、
 同一プロジェクト内に実装すれば、子フォーム側から、
 親フォームの StatusBar にアクセスする例として
   parent.statusBar1.Text = "FormChild opened.";
 のように実現できます。(種々の前提ご説明省略します。)

・ところが状況説明(3)を実現すると、
 親フォーム(FormParent)を子フォームにて宣言したりキャストしたり
 が出来ません。従って親フォーム側の public なフィールドなり
 メソッドなりにアクセス出来ません。
 子フォームプロジェクトに、親フォームプロジェクトを参照設定
 することができないからでしょうか。
 (できないのは当たり前でしょうか。)


フォーム継承やプロジェクト分割、それに対する参照設定に、
何か見落とし・勘違い・誤りがあるのでしょうか。

全般に理解不十分なところや、解決方法につきまして、
ご教示頂けましたら幸いです。
たつごろー
ぬし
会議室デビュー日: 2004/10/25
投稿数: 496
投稿日時: 2005-02-24 11:40
回答ではありません。
引用:

 ※DLLに分けている理由は以下のとおりです。
  ・子フォームが数種あり、いずれも(表現が悪いかもしれませんが)
   “孫フォーム”に相当する基底クラスがあり、
   フォーム継承によって出来上がっています。
  ・基底クラス(上の“孫フォーム”)はDLLに分けないと、
   フォーム継承が出来ないとの認識です。
  ・さらにそこから派生させた数種の子フォームも、
   他のアプリでの利用を将来的に考えてDLLとしました。


まずは動かす。からはじめましょう。
クラスが依存しあっていても、当面は目をつぶります。
コードが汚くなったらリファクタリングをしましょう。

動いていないのでは、ほかのアプリでの利用という将来は来ないです。
動いていたとしても、そのままそのDLLを流用するという将来が来る可能性はかなり低いですよ。そういうもんなんです。


_________________
たつごろー http://www.codeseek.net
MCSE MCSD.NET、MCDBA、MCSA、MCAD
Oracle Master Platinum 9i、Oracle Master Linux+



[ メッセージ編集済み 編集者: たつごろー 編集日時 2005-02-24 11:41 ]
kanai
ベテラン
会議室デビュー日: 2004/09/13
投稿数: 98
投稿日時: 2005-02-24 12:00
子フォームは、親フォームを単なるForm型としか認識していないので、
そこにToolbarがあるとか、Statusbarがあることは分かりません。

「StatusBar表示を変更する」など、親フォームが公開する操作・属性を
定めて、それを子フォームと共有する必要があります。

たとえば、子フォームのDLLに親フォームの基底クラスを導入し、
親フォームEXEから参照する、という方法があると思います。
kanai
ベテラン
会議室デビュー日: 2004/09/13
投稿数: 98
投稿日時: 2005-02-24 12:26
引用:

子フォームプロジェクトに、親フォームプロジェクトを参照設定
することができないからでしょうか。
(できないのは当たり前でしょうか。)



循環参照になるので、できないと思います。

また、EXEだとかDLLだとかは「配置」の問題であり、その前段階の
クラス設計が適切な限りはある意味どうにでもなります。

配置の問題を早くに考えすぎると、そこで配置上の制約が発生し、
場合によっては失敗を招く気がします。

引用:

・基底クラス(上の“孫フォーム”)はDLLに分けないと、
 フォーム継承が出来ないとの認識です。



別のDLLにしなくても、継承はできると思うのですが・・・




[ メッセージ編集済み 編集者: kanai 編集日時 2005-02-24 12:37 ]
会議室デビュー日: 2004/11/14
投稿数: 14
投稿日時: 2005-02-24 13:08
返信ありがとうございます。

kanai様のお話にありましたように、
間に親フォームの基底クラスを入れたら、という件から、
何かが出来そうな気がしてきました。
ただしちょっと試した限りでは、なかなかうまくできなくて
もう2、3日、確認してから、ご報告致したく存じます。

たつごろー様からは、まず動くものを、との話を頂戴致しましたが、
フォーム継承やプロジェクト分割を止めれば、
何の苦労もなく実現できるであろうと承知しているところです。
ただ本件状況を除くと、フォーム継承により思い通りに動いており、
ここまでに実装した機能はそのままに、何か良い手はないかと
質問させて頂いた次第です。

ところで、kanai様の
引用:

別のDLLにしなくても、継承はできると思うのですが・・・


は、そうなんですか?... よく認識していませんで、
そうしなければいけないものと勝手に思い込んでおりました。

即座のご報告ができませんが、確認出来次第に。
ありがとうございました。
渋木宏明(ひどり)
ぬし
会議室デビュー日: 2004/01/14
投稿数: 1155
お住まい・勤務地: 東京
投稿日時: 2005-02-24 13:22
引用:

間に親フォームの基底クラスを入れたら、という件から、
何かが出来そうな気がしてきました。
ただしちょっと試した限りでは、なかなかうまくできなくて
もう2、3日、確認してから、ご報告致したく存じます。



インターフェースを導入すれば簡単に解決します。

単純化したモデルケースは以下のとおり。

・新規にクラスライブラリプロジェクトを作成し、IFormParent インターフェースを定義する。

・IFormParent インターフェースに「親フォームが子フォームに公開するべきメソッド、プロパティ」を追加する。

・IFormParent のプロジェクトを、親フォームおよび子フォームのプロジェクトから参照する。

・FormParent の派生元に IFormParent を追加する。

・FormParent に、IFormParent が規定するメソッド、プロパティを実装する。

FormChildXXX は

IFormParent parent = (IFormParent) this.Parent;
parent.DoSomeTHing();

のように、親フォームへのアクセスを確保します。

_________________
// 渋木宏明 (Hiroaki SHIBUKI)
// http://hidori.jp/
// Microsoft MVP for Visual C#
//
// @IT会議室 RSS 配信中: http://hidori.jp/rss/atmarkIT/
会議室デビュー日: 2004/11/14
投稿数: 14
投稿日時: 2005-02-24 13:28
渋木宏明(ひどり)様、ありがとうございます。

インターフェースですか。全く頭にありませんでした。
というのも、見聞きするだけで、取り扱った経験がないためです。

結末は後にご報告させて頂きます。
会議室デビュー日: 2004/11/14
投稿数: 14
投稿日時: 2005-02-24 22:36
渋木宏明(ひどり)様に示して頂いた、
インターフェースを用いる方法で
簡単に実現できました。

ただ
(IFormParent) this.Parent は
(IFormParent) this.ParentForm としました。
(IFormParent) this.MdiParent でもよい?

いとも簡単に実現でき、感動しております。
大変勉強になりました。ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)