MVVMパターンを使用した場合のViewのフェードアウトについて行き詰まってます・・。
最近MSDMマガジンに載っていた「
Model-View-ViewModel デザイン パターンによる WPF アプリケーション」を参考に、MVVMパターンを使用したアプリケーションを作っています。
MVVMパターンはUIとロジックを切り離すとてもいいパターンだと思うのですが、その疎結合さゆえにView側の操作が柔軟に行えない感じがしています。
現状は参考サイトと同様に、「Window×1」 に対して「View×n」という、1つのWindowの中でViewの切り替えを行う画面遷移方式を取っています。
作っているアプリケーションはViewの遷移時にフェードイン・フェードアウトを行わせようと思っているのですが、Viewのフェードアウトの実装部分で行き詰っています。
MVVMパターンは「これがパターンだ!」という物はなく、柔軟に構築できるのだと参考サイトにも書いてありましたが、極力ViewとViewModel間での参照を無くしたいのでViewの表示はViewModelインスタンスをDataTemplateにて表示しています。
フェードインに関しては、UserControlを元にViewを作成しているので、UserControlのLoadedイベントをイベントトリガにしてアニメーションを行っているので問題はないのですが、Viewを閉じる(破棄)する際のフェードアウトが上手く作れません。
Unloadedイベントはフェードアウトのイベントトリガとして使用できない(既に要素ツリーから要素が削除されている為)ので、何をトリガとしてフェードアウトを行わせれば良いのか・・・・。
そもそもWPFでのフェードアウトの鉄板的なトリガを自分が分かってないだけなのかな?
参考サイトを例にとって例をあげると、Viewの起動・終了(実際はViewModelを)を管理しているViewModel(MainWindowViewModel)があります。
その管理しているViewModelより起動されたViewは、そのデータとなるViewModelのイベント通知にて管理しているViewModelに終了通知が送られ、ViewModelの破棄が行われ、Viewの終了となります。
例えばログイン画面があり、ユーザーIDとパスワード入力後にOKボタンにて検証を行い、正常の場合はそのままログイン画面が終了し、次画面へ遷移する物があったとします。
この場合、OKボタンをClickするとコマンドバインディングによってViewModelのコマンド処理が走り、ここで認証成功の場合、ViewModelよりイベント通知によって元のViewModelへ終了通知が行われますが、それはViewにとっては分からない部分です。
よってViewModelを管理しているViewModelも削除されるViewに対し終了通知を行えないのです。
一応、プロパティトリガの機構を使用して無理やりフェードアウトの実装は行えますが、とても汎用的ではい物で、ましてや開発現場などでは混乱を招く物でしかない実装は一応出来ました。
その実装方法と言うと、
- 事前実装 -
1、ViewModel側よりViewへの終了通知用の何かしらのプロパティ(プロパティトリガで使用される)をViewとViewModelでバインドさせておく
2、ViewModel側でViewのフェードアウトアニメーションが終了した場合の終了通知を感知する為の、何かしらのプロパティをViewとViewModelでバインドしておき、Viewよりそのプロパティが変更された場合のプロパティ変更後イベントをViewModel側で実装しておく
- 処理順序 -
1、ViewのOKボタンクリック時に呼ばれるViewModel側のコマンド処理内にて、終了通知用のプロパティを変更し、View側へ通知する
2、View側では1、で変更されたプロパティを元に、プロパティトリガを使用してフェードアウトアニメーションを行い、アニメーション終了時にアニメーション終了後通知用のプロパティを変更し、View側へ通知する
3、ViewModel側で2、で変更されたプロパティのセッター内にてプロパティ変更後のイベントを発行する
4.ViewModelを管理しているViewModelで3、で発行されたイベントのイベントハンドラ内にてViewModelの破棄を行い次画面へ遷移させる
こんな感じです。
実装するととても使いづらく、たまったものじゃありませんでした・・。
そもそもある動作を行わす時に、プロパティ操作で事を運ばすって事がスマートな感じではないし。
MVVMを使用した場合のViewとViewModel間での動作に関わる通知機構で良い実装ってどのように作るのでしょうかね?
もし「俺はこんな感じで実装している」や「MVVMを使用した場合のViewのフェードアウトはこうやるだろ~」みたいな事があれば教えてください。m(_ _)m