2015年02月01日

partial したフォームクラスをまとめ隊

 ニュースを見てたら、宮古島と伊良部島の間に日本一長い無料橋 ができたそうな。宮古島には一度行った事があって、伊良部島にも船で渡ったんで、どんだけ長いか想像できてしまうのですが、渡ってみたいなぁ。今オフシーズンだから安いよなぁ。調べたら 4日間4ダイブ付きで7万ですよ。ゴクリ。
 いつも沖縄行くときはここのツアー使うんだけど、いつも安すぎて不安になる。


 さて今日の本題です。C# で Windows アプリを開発していると、どうしてもフォームクラスにコードが集中するので、ソースファイルを分割したくなるんですよね。

 ありがたい事に C# には、partial という機能があるので、ソースの分割自体は簡単にできるのですが、例えば FormTest.cs の一部を FormTest.Core.cs というファイルに分けた場合、ソリューションエクスプローラーでの表示は以下のようになります。
20150201a.png
 フォームを新規作成した際に FormTest.cs と同時に作られる FormTest.Designer.cs については、あたかも FormTest.cs の関係者のように表示されるのですが、同じく仲間であるはずの FormTest.Core.cs は他人扱いですね。いったいどうしたら仲間として認めてくれるのでしょう。今回はそんなお話。

ドラッグして放り込めばいいんちゃうん?

 Windows のアプリのお約束としては、FormTest.Core.cs を掴んで FormTest.cs に放り込めば子要素になってくれそうなもんですよね。でも残念★。できません!
 それなら右クリックメニューなり、どこかのメニューにそれを設定するための機能がありそうなもんですよね。でも残念★。ありません!

 じゃあどうすればいいのよって事で、ぐぐってみたら、
csproj の xml を直接いじったらできました
 ‥‥‥とのことで。エーナニソレ。ホントに機能ないん?。最新の Visual Studio ならもしかしたら機能が追加されたかもしれませんが、とりあえずうちの VS2010 には公式の機能はない模様。この方法も、やってみたらできたというだけで、公式の仕様ではありません。

 まずは 必ず Visual Studio を閉じてから、csproj をテキストエディタで開いて、例えば今回の例なら "FormText.Core.cs" を検索してみると、
<Compile Include="TestForm.Core.cs" />
といった行があるはずなので、そこに FormTest.Designer.cs の項目の真似をして、 「このソースは TestForm.cs に依存していますよ」 という情報を追加してやります。
<Compile Include="TestForm.Core.cs">
  <DependentUpon>TestForm.cs</DependentUpon>
</Compile>
 これで、とりあえずはめでたく仲間として表示してもらえました。
20150201b.png
 ちなみに、このように表示されてなくても、ビルドも動作も全く問題ないので、単にものすごく気持ち悪いというだけです。気にしないなら気にしないで全然問題ありません。

なんですぐ勝手に決めつけてしまうん?

 で、さてソースも分割したし、見た目もしっくりしたし、さあこれで心おきなくコードが組めるぞ、と TestForm.Core.cs をダブルクリックしてみると、フォームデザイナーが開いて、ウインドウにボタンとか配置するモードになってしまうんですよね。普通にテキストエディタを開いて欲しいんだけど。

 そもそもですね、Visual Studio は ソースファイルの中身やら名前を見て、開くべきエディタを勝手に決めつけやがる んですが、挙動をみた感じだと、
  • Form や UserControl から派生したクラスの cs ファイルはフォームデザイナーが開き、それ以外の cs ファイルはテキストエディタが開く
  • でもなぜか、"Designer.cs" と付くファイルだけは意地でもテキストエディタが開く
‥‥それっておかしくね? 特に2つめ!
 どうせ特別扱いするんなら、Designer.cs でだけフォームデザイナーを開いてくれた方が遥かに合理的でしょ!。どうしてこうなった!。つーか勝手に決めんな!
 何とかしてこちらから開くべきエディタを明示的に指定できないものかと調べてみたら、なんと2つも方法がありました。

【方法1】 csproj 内にファイルの種別を指定する
 また csproj ですかよ。もちろんこれも非公式です。先ほどいじったように、ソースファイル名を検索して <SubType> 情報を追加すればOK。
<Compile Include="TestForm.Core.cs">
  <DependentUpon>TestForm.cs</DependentUpon>
  <SubType>Code</SubType>
</Compile>
 ‥‥のはずなんですけどね。プロジェクトを開いて何秒か経つと、勝手にまたファイルの中身を見られて、強制的に Form に戻されます。ホント死ねばいいのに。とりあえず VS2010 の時点ではこの方法は使えないぽい。
【方法2】 クラスに属性を追加する
 ソース内で、クラスに対して以下のように属性を追加すれば、必ずコード扱いになり、テキストエディタが開くようです。
[System.ComponentModel.DesignerCategory( "Code" )]
class クラス名
{
    ....
}
 確かにテキストエディタ開いたよイヤッホウ!。でもこれのキモは 「クラスに対して属性を指定している」 ため、TestForm.Core.cs に属性を追加した以上、同じクラスである TestForm.cs も TestForm.Designer.cs テキストエディタで開くようになってしまいます。使えん‥‥。
 なお、"Code" を "Form" にすると強制的にフォームデザイナーが開くようになりますが、その場合も Designer.cs だけは意地でもテキストエディタが開くという。ホント死ねばいいのに。
【方法3】 もう全部テキストエディタでいいんじゃね?↑
 冷静に考えるとですね、csファイルをクリックしてフォームデザイナーを開きたい事ってあんまないんですよ。フォームデザイナー開きたければ右クリックで開けるんだし。
 という訳で結局、少なくても VS2010 の時点では自動判別が雑すぎるので、全部テキストエディタで開いてくれた方がマシ という結論になりました。ホント死ねばいいのに。
 フォームクラスの cs ファイルを右クリックして 「ファイルを開くアプリケーションの選択」 を選び、 「CSharp エディター」 を 「規定値として設定」 すればOKです。

 今回は以下のページを参考にさせていただきました。ありがたい事です。
タグ:C# visual studio
posted by ひこざ at 22:41| Comment(0) | 開発 - 全般
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。