- PR -

カスタムコントロールから、デザイン時にプロジェクトのパスを取得する方法

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2008-11-27 11:45
 ざっと検索したところ、IReferenceService インターフェイス<microsoft.com> が使えるかもしれません。デザイン時アーキテクチャ<microsoft.com> も、一読ください。

 これは、「デザインの時のみ必要なのだから、実コードの中で取得するのではなく、クラスやメソッドの属性として何か指定するのではないか」と考え、MSDN を「デザイン時 属性」で検索し、「デザイン時アーキテクチャ」を見つけました。そこにインターフェイスの一覧と、簡単な説明がありました。
おとぼけ父ちゃん
会議室デビュー日: 2008/11/25
投稿数: 9
投稿日時: 2008-12-03 22:33
沢山の方に回答をいただき本当にありがとうございます。

いろいろ試して見たのですが上手くいきませんでした。
ネットで検索したところ、同じような内容の書き込みがあったのですがその内容も理解できませんでした。
見つけたサイトのURL
 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=38471&forum=7

この方は、自己解決としてソースを乗せていただいているのですが
--見つけたサイトの引用 -----------------------------------------
EnvDTE.Project proj;
... // proj初期化(略)
VSLangProj.VSProject vsProj = proj.Object as VSLangProj.VSProject;
IEnumerator reader = vsProj.References.GetEnumerator():
while( reader.MoveNext() )
{
VSLangProj.Reference refObj = reader.Current as VSLangProj.Reference;
MessageBox.Show( string.Format( "参照項目名 = {0}", refObj.Name ) );
}
--見つけたサイトの引用 -----------------------------------------
ソースとして省略されている、proj初期化部分が分からず試すことができない状態です。
この方法がわかれば、カスタムコントロールを使用しているプロジェクトの内容を使用できるのではと思っているのですが、方法を教えていただけないでしょうか

どうかよろしくお願いいたします。

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-12-04 01:42
話題が戻って申し訳ないですが。

引用:

おとぼけ父ちゃんさんの書き込み (2008-11-27 10:33) より:

引用:

にーさんの書き込み (2008-11-25 23:55) より:

デザイン時でなく、実行時にじゃんぬねっとさんのやり方を行うので良いような気がしますが、デザイン時にしたい理由は何なのでしょう。


回答ありがとうございます。
デザイン時に外部ファイルを読み込みたいのは、見た目に関するプロパティ群を管理しデザイン時にコントロールに適用し見た目を確認したいからです。


ここ反論になっていないです。 私が示した方法はどちらであってもデザイン時にデザインを確認することは可能です。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
おとぼけ父ちゃん
会議室デビュー日: 2008/11/25
投稿数: 9
投稿日時: 2008-12-04 09:34
回答ありがとうございます。

引用:

じゃんぬねっとさんの書き込み (2008-12-04 01:42) より:
話題が戻って申し訳ないですが。

引用:

おとぼけ父ちゃんさんの書き込み (2008-11-27 10:33) より:

引用:

にーさんの書き込み (2008-11-25 23:55) より:

デザイン時でなく、実行時にじゃんぬねっとさんのやり方を行うので良いような気がしますが、デザイン時にしたい理由は何なのでしょう。


回答ありがとうございます。
デザイン時に外部ファイルを読み込みたいのは、見た目に関するプロパティ群を管理しデザイン時にコントロールに適用し見た目を確認したいからです。


ここ反論になっていないです。 私が示した方法はどちらであってもデザイン時にデザインを確認することは可能です。



現在、カスタムフォームに外部ファイルを読み込むパスをプロパティに設定しているのですが、この方法だと複数人で開発しているのですがそれぞれにプロジェクトの保存場所が異なるため同じプロジェクトを開く度にカスタムフォームのパスを変更する必要があり困っています。

そこで、開いたプロジェクトのパスを取得する方法があればと考えたのですが上手くいかず、こちらのサイトに書き込みを行いました。

本当に説明が至らず申し訳ありません。
何か良い方法がございましたら教えていただけないでしょうか

よろしくお願いいたします。
108
常連さん
会議室デビュー日: 2007/12/12
投稿数: 45
投稿日時: 2008-12-04 12:53
1人だけ見当違いの投稿をしていたため削除させて頂きます。

[ メッセージ編集済み 編集者: 108 編集日時 2008-12-05 09:37 ]
まどか
ぬし
会議室デビュー日: 2005/09/06
投稿数: 372
お住まい・勤務地: ますのすし管区
投稿日時: 2008-12-04 21:51
引用:

おとぼけ父ちゃんさんの書き込み (2008-12-04 09:34) より:
現在、カスタムフォームに外部ファイルを読み込むパスをプロパティに設定しているのですが、この方法だと複数人で開発しているのですがそれぞれにプロジェクトの保存場所が異なるため同じプロジェクトを開く度にカスタムフォームのパスを変更する必要があり困っています。



逆に「なぜプロジェクトパスを求めることができないのか」の理由を考えてみてください。

プロジェクトパスは単にソースファイルがどこにあるかという意味でしかないのです。
そしてソリューションエクスプローラはソリューションに書かれている情報をもとに
ソースファイルの場所を再現しているだけです。
#ソリューションエクスプローラに見えているものが実行時環境であると勘違いしてはいけません。
つまり、概念的には開発ツールであるVSの管理項目であり、アプリケーションの動作の概念の項目ではありません。

アプリケーションの動きを記述するところに無関係な概念を取り入れようとしているので
きつい言い方になって申し訳ありませんが
現在の問題が起きるのは当然の結果といえますし、
上記の理屈を認識していれば今回の仕組みが選択肢として挙がることもなかったでしょう。

#これだけではあれなので

たぶん誰が考えても似たようなやり方になるでしょうが一例を書いてみます。

・設定パターンを洗い出して、パターンを列挙体にする。
・カスタムコントロールにはその列挙体型のプロパティのみを実装する。
・各パターンごとの設定処理はカスタムコントロール内に記述する。
・カスタムコントロールの既定のコンストラクタでプロパティ値による設定処理を実行する。

これでいけると思います。
ただし、やはり実行時動作というかクラスのメンバとは無関係のものを実装することには変わりません。
そこは、スコープを限定したりObsolute属性をつけたりDesignMode プロパティで動作を無効化したり
というような工夫をすればよいかと思います。
Shinichi Aoyagi
会議室デビュー日: 2004/10/12
投稿数: 1
投稿日時: 2008-12-04 23:51
おとぼけ父ちゃんさんがやりたいことって↓みたいな感じですよね?

・HTML に対する CSS のようにカスタムコントロールの設定などを外出しのファイルにしたい。
・その外出しのファイルは exe、もしくは、アセンブリからの相対パスにしたい。
・実行時には Application.ExecutablePath なり Assembly.CodeBase なりで exe のパスなんかはとれる。
・ところが、デザイン時にそれらを使うと devenv.exe の場所が返ってきてしまう。
・なので、デザイン時にはプロジェクトのパスを取得し、そこからの相対パスでファイルを取ってくるようにしたい。

皆さんこういうやり方はすべきではないという論調のようですが、そんなにまずいやり方ですかね?
私はなかなかいいやり方だと思ったんですが。。。
あと、「app.config に持てばいい」 という意見も出てたようですが、上記のような状況の場合、デザイン時に app.config を取得することもできなんいじゃないですか?それとも、app.config だけはデザイン時にも取得することができるようになってる?(すみません、私はこの辺よく知りません)

それと、確かに
 ・ClickOnce にすると外出しのファイルが取れなくなる。(HTTP でアクセスしないといけない)
 ・アセンブリからの相対パスとしていた場合、そのアセンブリ(カスタムコントロール)を GAC に入れると相対パスではうまくいかなくなる。
などいくつか制限もあると思います。
このあたりは理解しておいたほうがいいかもしれませんね。

と、前置きがえらく長くなりました(^^;
肝心の方法ですが、
http://blogs.msdn.com/mszcool/archive/2004/06/30/169793.aspx
こちらが参考になりませんか?
この記事は、ASP.NET のカスタム Web コントロールでデザイン時に EnvDTE.DTE を取得して web.config のフルパスを取り出そうとしています。
ASP.NET も Windows Forms もデザイン時はたいして変わらないはずです。
DTE の取得は

EnvDTE.DTE devenv = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");

としています。
"VisualStudio.DTE.7.1" の 7.1 はバージョンナンバーなので Visual Studio のバージョンによって変わってくるはずです。
お使いの Visual Studio に合わせて 8.0 なり 9.0 なり試してみてください。
なお、この方法で本当にデザイン時に DTE オブジェクトが取得できるのかは試していません。うまくいかなかったらごめんなさいです。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2008-12-05 01:27
なんか皆さん否定的ですけど、別に普通の要求だと思います。
たとえばデータセットデザイナでは、App.configの設定値(DB接続文字列の情報、実際に使ってるのはSettingの機能を通してですが)を、デザイナで利用できるようになっていますよね?
デザイナ上でDBに接続する必要があるんですから当たり前ですが。
実行時には実行時用の内容が構成ファイルから読まれて同じように動かせるわけです。

このVSの機能の考え方っておかしいですか?
私にはできて当たり前、当たり前に要求される動作だと思います。
コントロールなどのデザイン時サポート用の機能って何のためにあるんでしょう?
デザイナと適切に連携するためですよね?

※今回の話と同じ話ではないかもしれませんが、本質的な部分は同じと思います。

まあ、設定内容がアプリの設定情報保存とかであれば、Exeなどと同じフォルダにおくのは無理がありますが、読んでみた限りでは固定の情報(アプリなどで修正するのではない、たとえばDBの接続文字列などと同じような扱い)と思われますので、アプリと同一フォルダにおくのも別におかしな話ではありませんし。

Jittaさんが書かれている「IReferenceService インターフェイス」というのでいけるのかもしれません、ちょっと確認していないのでわかりませんが、試してみる価値はありそうに思われます。
※青柳さんが書かれているほうのも参考になりそうですね(まだ見てませんが)

デザイン時に色とか状態を見たいって、別に当たり前の要求ではないですか?
なんでみんなそんなにおかしいというのかがいまいち分かりません。
というか、「何が」そんなにおかしいといっているんでしょうか?


コントロールのプロパティでたとえば設定ファイル名を指定させる、あるいは構成ファイルで設定ファイル名を指定させる、という方法をとったとしても、いずれにしてもデザイン時に簡単に反映する方法はありません(上記IReferenceServiceなどの、デザイン時サポートの機能で何とかできるのだろうとは思いますが)。

このようなデザイン時のサポートをするのに、どうすればできるか?という質問ですよね?
っていうか私も知りたいですが。

設定値を直接構成ファイルに書くなら、Settingsとかでできるのかな?
記述の仕方が限定されるのと、あんまり詳しくないので本当にできるのかその辺はよく分かりませんが。

--追記
みんなって書いたけどみんなってほどみんなが言ってるわけではなかったですね、すみません。

デザイン時に設定情報を反映して表示したいってのはごく当たり前に思えるということと、
実際そういうことを簡単に行える方法が無いようなので、その方法を聞きたいのも良く分かるというのが、まあ言いたかったことです。


[ メッセージ編集済み 編集者: なちゃ 編集日時 2008-12-05 01:50 ]

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