ダイアログ・アニメーション・画面遷移 2010/11/6 第60回codeseek勉強会 第2回日本C#ユーザー会勉強会 尾上 雅則(@ugaya40) 自己紹介 尾上 雅則(おのうえ まさのり) フリーランスだったり、会社があったり。 C#er はじめて覚えたプログラミング言語 = C#1.0 もともとはサーバ側専門。たまにスマクラ Windows Forms 2009/6月ごろWPFに目覚め、パッケージをリリース。イベント 駆動で開発した所、非常に苦労し、以後ほぼ一年間MVVMに夢中。 VB.NET少々 Silverlightってなんでしたっけ? Twitter : @ugaya40 Blog : the sea of fertility – http://ugaya40.net Facebook : http://www.facebook.com/ugaya40 なぜこれらは難しい? どういう時に、ViewModelからViewを触り たくなる? 代表的なパターン ダイアログ アニメーション 画面遷移 ダイアログ ViewModelでMessageBox.Showする? 自動単体テストが・・・ ViewのコードビハインドからMessageBox.Showす る コードビハインド・・・ FileDialog系(Save/Open)はどうしよう? 戻り値が必要なパターン ダイアログ 実は2種類ある。 Viewが起点となって表示するダイアログ 実行確認系とか。 ViewModelが起点となって表示するダイアログ エラーダイアログ・終了前の保存確認とか アニメーション ICommandの実行前後にアニメーションを挟みたい 場合が多々ある。 コレクションの増減時にもアニメーションを挟みた い場面が多々ある。 View側で完結して欲しい処理 ViewModelには関わらせたくない 戻り値をViewModel側で処理したりする必要がない 画面遷移 実は最大の鬼門 パターンがたくさんある モーダルダイアログとしての遷移 新しいウィンドウを別に表示 Webページ的な遷移 ナビゲーション こいつはプログラミングモデルからして異なる。 共通する問題 いずれも、イベント駆動開発ではコードビハインドで処 理してきたパターン イベント駆動開発をしていると、コードビハインドは WPF/SLでは今までより増えるんです! Windows Formsより、WPFを選んだのは、UIの表現力が増した から! ASP.NETより、Silverlightを選ぶのは、WEBよりリッチなUIを構 築したかったから! イベント駆動開発では、UIの見かけのみに関わるコードがコー ドビハインドに爆発! イベント発生順依存のコードを保守するのは大変 BlendだけでUIを開発できないのも痛い 自動単体テストはどうしましょう? UI Automation系での自動単体テストは結局いつも実現さ れてませんでした 考えられてきた対処法もろもろ みんなの努力 ViewModelからViewを操作したくなるシナリオで は世界中の人がいろんな手法を考えてきました。 代表的な手法 インターフェース Viewにコマンド Messenger みんなの努力1 – インターフェース Viewは特定のインターフェースを実装する ViewModelはViewのインスタンスを、インターフェースの実装とし て持つ ViewModelはViewのコードビハインドに定義されたメソッドを、イ ンターフェース経由で呼んでやるイメージ。 プロジェクト: 1-InterfaceView みんなの努力1 – インターフェース 長所 一応疎結合は維持(たぶん。きっと。) インターフェースを実装したViewのスタブオブジェ クトを使えば、自動単体テストも可能。 短所 ViewModelにて、インターフェースをViewのインス タンスにキャストする事でViewを直接いぢり放題 きちんと管理しなければ、MVVMで開発している意味がな くなる 「きちんと管理」がそもそもできるのなら、そもそも設計 パターンを使用する意味は・・・ コードビハインドがある。 みんなの努力2 – Viewにコマンド Viewが、コードビハインドにてICommandを実装する ViewのXAMLにて、ViewModelのプロパティにView側で定義さ れたICommandを渡してやる ViewModelは渡されたコマンドをExecute! ダイアログ表示ロジック などはここに記述 コードビハインドで定義した ダイアログ表示用コマンド Viewで定義された コマンドを格納するプロパティ ViewのXAMLで、ViewModelのプロパティにViewのコマンドを渡す ViewModelは、渡されたコマンドを処理の中で自由に実行すれば良い。 Interfaceの時と同じことを、ViewModelがViewのインスタンスを持つこ となく実現している プロジェクト:2-ReverseCommand みんなの努力2 – Viewにコマンド 長所 バインディング機構だけで疎結合を実現しているのは 素敵 単体テスト問題なし 短所 コードビハインドがある ViewModel側がコマンドで乱雑になる 戻り値を受け取るのが大変 みんなの努力3 – Messenger MVVM Light Toolkit http://www.galasoft.ch/mvvm/getstarted/ Messengerというアプローチ ViewModelは、Viewに何らかのアクションを起こし て欲しいタイミングでメッセージ(実体はイベント)を 発信する。 コールバックは Viewがメッセージに対応するアクションを終えた後に実行される みんなの努力3 – Messenger Viewはイベントを監視し、送られてきたメッセージ に対応するアクションを実装する イベントの解除などは、補助ライブラリ側で責任を持つ必要がある プロジェクト:3-SimpleMessenger MVVM Light Toolkitを使って実装しました! みんなの努力3 – Messenger 長所 一応疎結合は維持(たぶん。きっと。) 単体テスト問題なし 受け入れられている 最近ではWindows Phone 7 のサンプルが良くMVVM Light Toolkitを使用して作られていた 短所 乱用しやすい 使ってみるとわかるが、ただのイベントの仕組みをラップ しただけの仕組みのため、「きちんと管理」しないと MVVMを使う意味が・・。 「何も考えずに使うと」コードビハインドがある。 みんなの努力 – 共通した問題 コードビハインドがある BlendだけでViewが作れない 結局管理が難しい 「きちんと管理」しないといけない=略 やっぱり微妙にクールじゃない XAMLで書けない部分を、C#で書く。 でもそれはコードビハインドに書くわけではないのです。 コードビハインドの抹殺 - ビヘイビア・トリ ガー・アクション ビヘイビア・トリガー・アクションを用いる事で、 コードビハインドの抹殺が可能! ビヘイビア なんらからのイベント・ステートに基づいて、オブ ジェクトの状態を遷移させるのが主な役割 トリガー&アクション 任意のトリガーを起点として、任意のアクションを実 行させられる。 (インフラが整っていれば)C#どころか、XAMLを手 で一行も書かなくてもBlendのGUIで設定可能! コードビハインドの抹殺 – ビヘイビア ビヘイビアとは、添付プロパティの仕組みを使って、 オブジェクト自体が持たない状態と動作を、オブ ジェクトの外部から追加定義するもの。 コードビハインド抹殺 – ビヘイビア 実はビヘイビアと言われるものは2種類ある .NET Frameworkだけで作成できるビヘイビア 通称 添付ビヘイビア(Attached Behavior) 実装に時間がかかる Blend SDK 付属アセンブリを使用するビヘイビア ただビヘイビアと呼称 Blend SDKアセンブリ = System.Windows.Interactivity.dll 基底クラスが定義されていて、実装が楽。 System.Windows.Interactivity.dllにあたるものを自前実 装する事もできるが、今後の標準化の方向などを考えると 無駄かと。 プロジェクト:4-SimpleBehaviors @okazuki さんのブログの素敵なサンプルをぱくらせていただきました http://d.hatena.ne.jp/okazuki/20100906/1283778339 コードビハインドの抹殺 – トリガー&アク ション Trigger 言葉通り。後述するアクションのトリガーとなる Action 任意のトリガーによって起動されるアクション Blend 定義済Trigger & Action ChangePropertyAction EventTrigger DataTrigger KeyTrigger PropertyChangedTrigger InvokeCommandAction StoryboardCompletedTrigger TimerTrigger GotoStateAction PlaySoundAction LaunchUriOrFileAction プロジェクト:SampleTriggerAndAction コードビハインドの抹殺 ビヘイビア & トリガーとアクションの使用はBlend SDKが前提 Blend SDKは、Expression Blendを持っていなくて も単体で導入が可能! .NET Frameworkだけで使おうとすると EventTrigger以外のトリガーはスタイルやテンプレー ト以外では使えない トリガーもアクションも独自定義できない 基底クラスがinternal コンストラクタ (TriggerBase/TriggerAction) ビヘイビアの実装が非常に大変 Blend SDK Blend SDKを使うと.NET Frameworkだけでは不可能な、 トリガー&アクションの独自定義が可能 しかも実装はむちゃくちゃ簡単です。詳しくはBlend SDK のヘルプ参照 Blend SDKには最初から膨大な数のビヘイビア・トリ ガー・アクションが定義されている BlendでUIの開発を行っていると、標準で利用可能 Blend SDKのライブラリは明示的にプロジェクトで参照 しなくても、Blendでプロジェクトを読み込むだけで勝 手に参照が追加される。 Blend SDK を使用しないMVVMなど個人的には絵空事。 ビヘイビア・トリガー・アクションで出来る 事 Viewが起点となる動作や、ViewModelのプロパ ティの変化が起点となる動作ならば、結論からいえ ば何でもできます UI開発者はBlend上で、一切のコードを書かず (XAML含め)ビヘイビア・トリガー・アクションの 引数を指定可能。 ビヘイビア・トリガー・アクションで出来る 事 なんでもできる、けど、だからこそ・・・ 開発者みんなが自由に作ったらやっぱり大変な事に・・。 ビヘイビア・トリガー・アクションは定義済のものとして インフラに組み込んでしまうべき。 都合の良い事に、ビヘイビア・トリガー・アクションはビ ジネスロジックのドメインと結合しにくい つまり、再利用が容易 ビヘイビア・トリガー・アクションは画面ごとに定義が必 要なものではありません! Model呼び出しを伴わない様な処理はすべて処理できます。 コードビハインドの抹殺 – まとめ ビヘイビア・トリガー・アクションを使用する事で、 Model呼び出しを伴わないような処理は全てコード ビハインドを使わずに処理できる。 ViewModelのプロパティの変化を監視して、Viewを 遷移させることなども可能。 Blend SDK使用が前提 しかし戻り値を返せないため、ViewModelを介して Modelと連携するような処理は苦手・・・ ViewModelを介して、Modelと連携するような処理はどうす るか? ViewModel起点アクションの処理 MVVM Light ToolkitのMessengerを思い出してくだ さい! Messengerがコードビハインドを使用するのは、メッ セージに対応するアクションを記述する時だったはず もしメッセージに対応するアクションが、全てビヘイ ビア・アクションに移動すると・・ Pattern & Practice Prismの採用方式です! プロジェクト:MessagingAndBehaviors Pattern & Practice Prismが採用している手法なので Prismで実装してみました。 Messenger And Behaviors すいません。パターン名はオレオレです。 ViewModelからMessageを送信(イベント発行)する コードはほぼ一緒 Messenger And Behaviors しかしメッセージに対応するアクションはPrismでは XAML(トリガー & アクション)で書きます。 MVVM Lightの例ではコードビハインドに書いていました。 Messenger And Behaviors Messageに対応するアクションをTriggerActionに 移動する事でもう一つ利点が生まれました ViewModelは純粋な意味でメッセージを発信し、 Viewはメッセージに対応する好きな実装を GUI(Blend)で選ぶ事が出来ます! InteractionRequestTrigger ChangePropertyAction ダイアログを表示するアクション GotoStateAction 好きなActionを選べます InvokeCommandAction バルーンを表示するアクション Messenger And Behaviors 今までのパターンのすべての長所を備え、かつ短所が少ない。 現在・今後も主流となるように思えます! Pattern & Practice Prismも採用 これが最大の根拠 MVVM Light Toolkitも、実はこの形を意識した実装がされてい ます しかし同時に、コードビハインドも使用できるよう設計されている Cinch / Caliburnなどの他のメジャーなMVVMライブラリも採 用しています 現在のPrismは不完全なので注意が必要 実際の所、パターンの使い分け ダイアログはどうなる? View起点ダイアログの場合 トリガー&トリガーアクションを用いる事で、全て コードビハインドなしの解決が可能 ViewModel起点ダイアログの場合 エラーダイアログや対応確認ダイアログの場合 ビヘイビア・トリガー・アクション用にいちいちプロパ ティを用意する? ビヘイビア・トリガー・アクションだけでは、まだまだ強 引な実装 だからこそ、Messenger And Behavior プロジェクト:7-DialogSample アニメーションはどうなる? XAMLのみで完結できるアニメーションとビヘイビ ア、トリガー、アクションの相性は抜群 コードビハインドなしで、アニメーションを処理の 合間に挟み込める プロジェクト:8-AnimationSample 画面遷移はどうなる 基本的にはMessenger And Behaviorを使います。 実はTODOです. 引数を新規画面に引き渡す場合などを考慮すると、 Messenger And Behaviorを使うのがまず妥当に見えます しかし実際に表示するViewのクラスは、 VMが指示するんでしょうか? メッセージを受け取ったViewが指定するんでしょうか? とりえあずダイアログと同じように実装は可能です. Messageの中に、新規画面のViewModelを含める事にはなるで しょう 悩ましい所はどんな基準で実装する? まとめ。 MVVMでの実装に悩む時 まずは問題となる機能が、表示のみの機能なのか、 Model呼び出しに影響を与える機能なのかを考える 表示のみの機能 例) アニメーション 実行通知ダイアログなど → Blendだけで構築できるのが望ましい Model呼び出しに影響を与えうる機能 例) FileDialo系などの、戻り値をビジネスロジックで処理する必要の あるダイアログ 画面遷移など →ViewModel経由、Modelとの連携が不可欠 表示のみの機能の実装指針 ビヘイビア・トリガー・アクションで解決する 典型的なパターンを一度インフラとして実装してしま えば、新たにトリガー・アクションを実装する必要の ある場合などほとんどない ビヘイビア・トリガー・アクションは基本的にビジネスロ ジックのドメインと非結合なため、インフラとして全社単 位・あるいはフレームワーク単位での管理が容易 インフラ(ビヘイビア・トリガー・アクション)が 整っていれば・・・ BlendだけでUI(View)の開発をする事が可能になる コードを触る必要がなくなる! Model呼び出しに影響を与えうる機能の実装 指針 Messenger And Behaviorsで解決する 現在あるパターンの中で最も短所が少なく、長所が多 い方法 こちらもインフラ化しやすい インフラが整っていれば・・・ View側は、ViewModelから発されたメッセージに応 じて自由な表現をBlendだけで実現できる MVVMでの実装は面倒(マゾい)? DelegateCommmandやRelayCommand、ビヘイ ビア・トリガー・アクションはビジネスロジックの ドメインに結合していません。 インフラ化が容易という事。標準ライブラリで採用さ れれば、まったく面倒ではなくなる。 Blendの使用が前提ならば、むしろイベント駆動開発 よりはるかに楽です! MVVMでの実装は面倒(マゾい)? ViewModelの記述が冗長? ViewModelは自動生成させましょう。 ViewModelを自動生成させるために、Modelにすべてのビ ジネスロジックを載せましょう。 単純なデータ型のModel×。 詳しくは伊藤さんのセッションで! なによりもBlend使わなきゃ、WPF/SLの存在その ものがマゾい MVVMは業務ではまだ早い? はい。インフラが整備・統一されていない現状では 業務に採用するにはまだ早いです。 DelegateCommandとRelayCommandすら統一され ていない。 機能的には同じなのに。 今後はPrismに合わせていくのが無難かも。 Message And Behaviorsは各種メジャーMVVM補助 ライブラリではほぼ同じ形で実装されています しかし統一されていないのです 私見 MVVMの将来 私見ではMVVMはASP.NET MVCをWPF/SLの世界に持っ てこようとしたもの。 でもWEBシステムそのもののシンプルなアーキテクチャ上 の制約がWPF/SLにはない。 だからそのまま持ってこれなかった。 Pattern & Practice PrismはMVVMインフラにもなろう としている。 将来的には標準ライブラリに取り込まれるのでは? 既存スキル・規模との兼ね合いを考えると、ASP.NETと ASP.NET MVCみたいに、WPF(SL)とWPF(SL) MVVMみ たいにテンプレートが別れていくのでは?
© Copyright 2024 ExpyDoc