お久しぶりです。
ブログを更新していないしばらくの間、WPFをいじくり倒してました。おかげさまで、超簡単なデスクトップアプリケーションならなんとかつくれるようになりました。
というわけで週末は勉強がてらWPFでクッキークリッカーっぽいものをつくって遊んでました。
そこで感じたのが、
複数ウィンドウでデリゲートとかイベントとか書いてるうちにクラス間の関係が密結合になってしまうということ。
こういう場合、一つのクラスの規模が大きくなってきて ある属性をクラス化して分離したくなった時とかになかなか面倒くさいので、
一つメディエータみたいな感じのクラスが欲しい。
でもエントリポイントがWPFの一クラスだとあまり綺麗な構造になりそうもないので、
いっそのことエントリポイントをWPFのクラスじゃなくて通常のC#クラスにしてしまって、WPFを分離してはどうか。
さらに各描画用インスタンスを保持するクラスを用意して、複数ウィンドウ間でのイベント処理を楽にしてはどうかという発想に至った。
(API化すれば良い気もするが)
*なお、この記事はC#/WPF超初心者が執筆しているので、参考にする場合は十分に注意してください。また、「いやそもそもこうした方が楽じゃね」っていうところに関してはどんどんご指摘いただければ幸いです。
プロセス
1. 「空のプロジェクト」を選択。
2. エントリポイントになるクラスの追加。
3. とりあえずコンストラクタを書いておく。
* ここまでは通常のC#プログラムの作成と同じ。
4. Lib/Display ディレクトリの作成
5. Directory 内に WPFクラス FrontWindow.xaml / FrontWindow.xaml.cs の作成
6. .NET環境とかだと デフォ値で UserControl になっているので、xaml, xaml.cs ともに 基底クラス云々を Window に差し替え。
7. さらに WPFクラス App.xaml の作成。
8. UserControl → xaml, xaml.cs ともに 基底クラス云々を Application に差し替え。
9. System.xamlのアセンブリ参照が追加されていない場合は追加。
10. Display 内に メディエータとなる DisplayBaseクラス の作成。
11. DisplayBaseクラスに ShowFront() メソッドの追加。
public FrontWindow FW; public Application App = new Application(); public void ShowFront(){ FW = new FrontWindow(); FW.Show(); App.Run(FW); }
App.Run(FW) という形にする理由として、
Showメソッド自体そもそもnon-blocking callで、普通に呼び出してもウィンドウがパッと開いて閉じてしまうから。
12. エントリポイントのクラスのコンストラクタの書き換え。
[STAThread] public static void Main(){ DisplayBase Display = new DisplayBase(); DisplayBase.ShowFront(); }
STAThreadをつける理由として、
WPF自体 STAThread というスレッド以外で動作させられないようになっているので、
通常のエントリポイントからWPFオブジェクトを呼び出してしまうと例外が飛んでしまうから。
13. 毎回立ち上がるコマンドプロンプトを消す。
プロジェクト > ●●(プロジェクト名)のプロパティで出力の種類「コマンドプロンプト」になっている部分を「Windowsアプリケーション」に選択しなおす。
だん。
アドバイスなどございましたらどしどしご指摘いただければ幸いです!
それではまたm(_ _)m
Written by Nisei Kimura ( 木村 仁星 )