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


フィードバック

# re: [WPF] MVVMを使用した場合のViewのフェードアウトの実装方法について

2009/04/17 11:17 by trapemiya
う~ん、どうやるんでしょうね? BindingオブジェクトはINotifyPropertyChangedを使って通知できますが、そういった仕組みが無いと無理のような気がします。例えばアニメーション完了通知用のオブジェクトを作って、INotifyAnimationEndedみたいなインターフェースでアニメーション終了を伝えるとかで何とかならないかなぁ・・・。
View -> アニメーション完了通知用のオブジェクト -> ViewModel
WindowsフォームでいうところのBindingContextみたいな感じというか・・・。でもView側にXAMLだけでINotifyAnimationEndedは実装できないだろうから(?)、どうしてもView側でコードを書かなくちゃいけなくなるかな・・・?

# re: [WPF] MVVMを使用した場合のViewのフェードアウトの実装方法について

2009/04/17 20:51 by kazuto
>trapemiyaさん

コメント有難う御座います。
無理やりやれば実現不可能ではないのですが、良い実装がいまだに出来ていません。

自分の理想はXAMLだけで実現可能にしたいと思っています。
View側のXamlで

<UserControl Fadable="True" LoadMode="FadeIn" CloseMode="FadeOut">
</UserControl>

のような感じが一番理想だと思ってます。
このような記述がUserControlレベルで出来るのであれば、無理やり実現可能にする為のカスタムコントロールを作成・提供する必要もなくなると思いますので。

trapemiyaさんのコメントの「View -> アニメーション完了通知用のオブジェクト -> ViewModel」って所で、少し思いついた事があるので試してみます。
ViewとViewModelの結合度合いが少し上がる感じになりそうですが、添付プロパティを使用して通知用のオブジェクトを実装できそうです。

実装が実現出来れば改めてエントリさせて頂きます。

# ??????????????????????????????&#8230; &laquo; P2 - SharpLab.

2009/04/17 22:31 by Pingback/TrackBack
??????????????????????????????&#8230; &laquo; P2 - SharpLab.

# [WPF] MVVMを使用した場合のViewのフェードイン・フェードアウト用ヘルパクラスの実装

2009/04/21 21:42 by .NETな日々
[WPF] MVVMを使用した場合のViewのフェードイン・フェードアウト用ヘルパクラスの実装

# [WPF] MVVMを使用した場合のViewのフェードイン・フェードアウト用ヘルパクラスの実装

2009/04/21 21:49 by .NETな日々
[WPF] MVVMを使用した場合のViewのフェードイン・フェードアウト用ヘルパクラスの実装

# re: [WPF] MVVMを使用した場合のViewのフェードアウトの実装方法について

2009/05/28 11:23 by 通りすがり
詳細は確認していませんが、以下がは参考になるかもしれません。

TransitionContainer: Easy transitions between views:
http://blog.pixelingene.com/?p=12

# re: [WPF] MVVMを使用した場合のViewのフェードアウトの実装方法について

2009/05/28 12:59 by kazuto
>通りすがりさん
コメント有難う御座います。
拝見させて頂いた所、とても綺麗な画面遷移ですね。
このようなヘルパコンテナクラスを作成するのも良いですね。
時間を取ってじっくりと拝見させて頂きます。
コメントの入力
タイトル
名前
Url
コメント