Building Silverlight Large Scale Application Using MVVM

2,387 views
2,263 views

Published on

MVVM in Silverlight presentation for a SI partner site training in 2010.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,387
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
25
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide
  • 悩ましいのは、View上のいろんなイベント処理をいかに分離コード無しでコントロールするか、という点理想的にはViewはBehaviorを駆使して・・・、と行きたいところだが、業務系のシナリオを考えると難しい?スライド27 Commanding、28にあるEvent Aggregator、このあたりの明確な指針を出したい
  • // Warning: DEMO CODE AHEAD // Your ViewModel should not define your data for your Model :-) // Instead, it could make a call to a service to get the data for the Model.
  • // Warning: DEMO CODE AHEAD // Your ViewModel should not define your data for your Model :-) // Instead, it could make a call to a service to get the data for the Model.
  • Building Silverlight Large Scale Application Using MVVM

    1. 1. Silverlight を使ったLarge-Scale Applicationの構築- MVVM及び Prism のご紹介 - <br />鈴木 章太郎<br />アーキテクトエバンジェリスト<br />マイクロソフト株式会社<br />http://blogs.msdn.com/shosuz/ <br />Twitter : @shosuz <br />
    2. 2. アウトライン<br />MVVM<br />Model – View – ViewModel<br />何をするものか<br />どこで使えば一番うまく使えるか<br />応用<br />Prism<br />MVVMを有効に使うために<br />ギャップを埋めるために<br />オプション<br />
    3. 3. ゴール<br />Silverlight におけるMVVM の重要性<br />ゴールを達成するためには多くの手段がある<br />実際に動かしてみよう<br />MVVM イネーブラについて学ぼう<br />Prism<br />独自のものを作成しよう<br />
    4. 4. 他にも MV_ とついているものが…?<br />MVVM<br />MVC<br />MVP<br />MV????<br />アプリケーション構築において、メンテナンス性やスケーラビリティ確保のために、一般的に受け入れられているパターン<br />
    5. 5. Model-View-ViewModel全体像MVVM, Prism, MEF - WCF RIA Services連携<br />WPF、Silverlight の疎結合 ソリューションのパターン<br />下記の実装を行う (トライアド)<br />Model<br />Data(Web)Service のエンティティ(をラップする)<br />WCF RIA ServicesをModelと することも可能<br />ViewModel<br />Modelを UI に合わせて公開する<br />View<br />ViewModelをXAML等でバインドする<br />参照:http://msdn.microsoft.com/ja-jp/magazine/dd458800.aspx<br />
    6. 6. MVVMどんなものか?なぜ必要か?<br />関心の分離<br />View = UI を担当<br />Model = 純粋なデータを含む<br />ViewModel = バインディングを通じたView と Model との間のコミュニケーション<br />Silverlight と WPF とで有効活用可能<br />XAML ベースのデータバインディング<br />テスト可能<br />
    7. 7. MVVMどんなものか?なぜ必要か?<br />Model :INotifyPropertyChanged、IDataErrorInfoを実装しているクラス (UI要素は持たず、Setter/Getterとしてのプロパティを持つのみ)<br />ViewModelが取り扱うデータを保持するもの<br />ViewModel:INotifyPropertyChangedを実装しているクラス (UI要素は持たず、ビジネスロジックやサーバーとの通信を担当する)<br />多くはObservableCollectionとしてViewにバインドするデータ(Model)を取得し、保持するもの<br />分離コードでCommandとイベントハンドラ(Command Receiver)の対応付けを行う<br />Expression Blendのオブジェクトデータソースとしてスタティックリソース宣言が可能(ドラッグ&ドロップでUI構築)<br /> View:<br />XAMLによるUserControl (UI要素のみ)<br />ViewModelから提供されるデータ(Model)を2-waysデータバインドにより表示・更新する<br />XAML側でCommandの宣言を行う<br />できれば分離コードを一切もたないdumbコントロールとしての実装が望ましい(ViewModelの割り当てをViewの分離コードで実行することもできるが、View –ViewModelの分離が不明確になる可能性がある)<br />
    8. 8. The MVVM のトライアドすべてを一緒に<br />View<br />コントロールにデータを表示<br />UI フレンドリーなエンティティや、UI 状態、アクション<br />データを表すエンティティ<br />ViewModel<br />Model<br />
    9. 9. ModelMVVM<br />データを表す<br />エンティティ<br />どこから取得したデータかは知る必要なし<br />WCF サービス、WCF RIA Services 等々<br />バリデーションを含む場合あり<br />
    10. 10. ViewMVVM<br />画面, UI, SilverlightのUserControl<br />UI のルック&フィールを担当<br />情報を表示<br />バインディングを通じて、ViewModelとコミュニケート<br />
    11. 11. ViewModelMVVM<br />MVVM トライアドのためのロジックのメインソース<br />Model をView と接続する<br />Viewを抽象化する<br />View にバインドされたPublic プロパティ<br />INotifyPropertyChangedと、INotifyCollectionChangedとによる、バインディングを通じた View との会話<br />バインディングを通じたView からの変更の通知<br />MVVMトライアドの外部とのコミュニケートのためのサービスの呼び出し<br />
    12. 12. MVVMはどこから始めるのが良いか?MVVM バリエーション<br />View は ViewModelと何らかの関連性を持つ<br />幾つかの実施可能なオプション<br />View First<br />View Model First<br />MVVM トライアドの個々のパーツのメンテナンス<br />
    13. 13. View First MVVM Variations<br />ViewModelは View の XAMLの中のスタティックなリソースとして宣言される<br />Expression Blend で作れる<br />もう一つの方法としては、ViewModelをView の分離コードで作成する<br />
    14. 14. View First MVVM<br />demo <br />
    15. 15. ViewModel FirstMVVM バリエーション<br />View は、ViewModelのコンストラクタにインジェクト(=注入)される<br />Example:<br />View がDependency Injection を使って作成されると、ViewModelが 作成される<br />
    16. 16. View と ViewModelとの結び付けMVVM バリエーション<br />View は ViewModelと何らかの形で一対になる<br />ViewModelと View は一旦作成され、中間段階を経て、その後一対となる<br />
    17. 17. View とViewModelとの結び付け<br />vm = new MyVM();<br />view = new MyView();<br />view.DataContext = vm;<br />// With Unity<br />vm = container.Resolve<IMyVM>();<br />view = container.Resolve<MyView>();<br />view.DataContext = vm;<br />
    18. 18. Prism についていつでも選択可能<br />Prism は、オプションのセット<br />使いたいものだけを選んで使い、残りは無視して良し<br />例 : <br />モジュールとコマンドは選ぶが、イベントアグリゲーションとリージョンは無視する<br />Prism: patterns & practices Composite Application Guidance for WPF and Silverlight site<br />http://www.codeplex.com/CompositeWPF <br />
    19. 19. Prism の技術コンセプト<br />Commands<br />Shell<br />Modules<br />Bootstrapper<br />Event Aggregation<br />Container<br />Regions<br />Unity and DI<br />
    20. 20. Bootstrapperスタートするための機能<br />アプリケーションを起動<br />メイン UI コンテナをスタート (Shell)<br />(必要に応じて)モジュールの登録とロード<br />グローバルシングルトンの登録 (オプション)<br />通常 “Bootstrapperプロジェクト” に含まれる<br />
    21. 21. ShellメインView<br />メイン UI コンテナ<br />ロードされ得るすべての Viewをホスト<br />リージョンに分割可能<br />Shell 自身は、その中に何がロードされるかを知らない<br />
    22. 22. RegionsContent エリア<br />View を配置できる Shell の中のエリア<br />名前を付ける必要あり<br />コンテキストを内包可能 (オプション)<br />RegionManagerによりRegionをメンテナンス可能<br />
    23. 23. ModularitySelf Contained Modules<br />ユーザーにとってはシームレス<br />分割して開発される<br />他のモジュールを参照してはならない<br />Solution はModules に分割される<br />Example:<br />City government application<br />Module 1: Managing land parcels<br />Module 2: Traffic light administration<br />Module 4: City Parks <br />Modules は、infrastructure と Models をシェアする<br />
    24. 24. Dependency InjectionUnityの利用<br />Unity 又は他の DI ツール群 (例:Ninject)<br />テスト可能でモック作成<br />抽象化<br />コンテナオブジェクトにより、クラスがそのインターフェースに従って登録される<br />インターフェースをリクエストされたとき、コンテナは、当該インターフェースと一緒に登録されたクラスを、作成する<br />シングルトンのサポート<br />
    25. 25. クラスへのインターフェースの登録<br />container.RegisterType<br /> <IMyViewModel, MyViewModel>();<br />
    26. 26. コンクリートClass の作成<br />container.Resolve<IMyViewModel>();<br />
    27. 27. Infrastructure共通のTools<br />Silverlight クラスライブラリプロジェクト<br />モジュールのために共有可能なアイテムを含む<br />Classes<br />Assets<br />Resources<br />何の参照も作成しない<br />純粋なライブラリ<br />
    28. 28. Commandingアクションとリアクション<br />データバインディングを通じた View とViewModelとの間のイベントを許可<br />ViewModelが宣言するのは Command receiver<br />Command は XAMLの中で宣言される<br />Button - Click<br />ListBox (Selector) – Selected<br />Command は、ViewModel の Command receiver にデータバインドされる<br />ルールベースで disabled/enabled 設定可能<br />
    29. 29. Commanding 実装のための5つのステップ – 前提<br />Silverlight 4 プロジェクトにおけるICommand実装は、数ステップで足りる<br />問い合わせの多い個所なので、下記にCommanding 実装のためのシンプルなテクニックを記述する<br />
    30. 30. Commanding 実装のための5つのステップ – ICommandの実装<br />最初のステップは、ICommandインターフェースクラスの実装<br />このクラスはCommanding アスペクトを管理する<br />他にも色々オプションがあるところ、ここではシンプルなICommand の実装方法を紹介<br />当該 DelegatedCommandクラスで実装するのは、ICommandのCanExecuteメソッド、Execute メソッド、そして、CaneExecuteChangedイベント<br />このコードはそのままコピー&ペーストして利用可能<br />
    31. 31. Commanding 実装のための5つのステップ – ICommandの実装 ①<br /> public class DelegateCommand : ICommand<br /> {<br />Func<object, bool> canExecute;<br /> Action<object> executeAction;<br />boolcanExecuteCache;<br /> public DelegateCommand(Action<object> <br />executeAction, Func<object, bool>canExecute)<br /> {<br />this.executeAction= executeAction;<br />this.canExecute= canExecute;<br /> }<br />… <br />
    32. 32. Commanding 実装のための5つのステップ – ICommandの実装 ②<br />#region ICommandMembers<br /> public boolCanExecute(object parameter)<br /> {<br />booltemp = canExecute(parameter);<br /> if (canExecuteCache != temp)<br /> {<br />canExecuteCache= temp;<br /> if (CanExecuteChanged != null)<br /> {<br />CanExecuteChanged(this, new <br />EventArgs());<br /> }<br /> }<br /> return canExecuteCache;<br /> }<br />
    33. 33. Commanding 実装のための5つのステップ – ICommandの実装 ②<br />・・・続き・・・<br /> public event EventHandlerCanExecuteChanged;<br /> public void Execute(object parameter)<br /> {<br />executeAction(parameter);<br /> }<br />#endregion<br />}<br />
    34. 34. Commanding 実装のための5つのステップ – Commandの定義<br />//ICommand を表示するための Public プロパティ<br />を ViewModelに追加<br />//このプロパティは 、通常は、ボタン等により、 <br /> View にバインドされる<br />public ICommand<br />LoadProductsCommand{ get; set; }<br />
    35. 35. Commanding 実装のための5つのステップ – Command の作成<br />//ViewModelのコンストラクタの中で、<br /> 1で作成したコマンドプロパティを設定する<br />LoadProductsCommand= <br /> new DelegateCommand<br /> (LoadProducts, CanLoadProducts);<br />
    36. 36. Commanding 実装のための5つのステップ – ViewModelの作成<br />//ViewModelが View からアクセス可能なこと<br /> を確認する<br />// 様々な方法があるところ、シンプルに View <br />の XAML 中の Static Resource として作成<br /><UserControl.Resources> <local:ProductViewModel<br /> x:Key="vm"/><br /></UserControl.Resources><br />
    37. 37. Commanding 実装のための5つのステップ – Command のバインド<br />//ボタンコントロールを追加し、当該コマンドプロパティを ViewModel<br />の中で作ったコマンドにバインドする<br />//当該Command に parameter を渡したい場合には、 <br />CommandParameterプロパティを、当該 View の中の要素にバインド<br />できる (通常は parameter は必要ないが、例として実装) <br /><Button <br />Content="Load" Width="120" <br />Command="{Binding LoadProductsCommand}" CommandParameter=<br /> "{Binding ElementName=<br />FilterTextBox, Path=Text}" <br />/><br />
    38. 38. Commanding 実装のための5つのステップ – ProductViewModel完成品<br />public class ProductViewModel : ViewModelBase<br />{ <br />public ProductViewModel()<br />{<br />this.Products= new ObservableCollection<Product>(); <br />this.AllProducts= new ObservableCollection<Product>();<br />this.AllProducts.Add(new Product { ProductId = 1, ProductName = "Apple" });<br />this.AllProducts.Add(new Product { ProductId = 2, ProductName = "Orange" });<br />this.AllProducts.Add(new Product { ProductId = 3, ProductName = "Banana" }); <br />this.AllProducts.Add(new Product { ProductId = 4, ProductName = "Pear" })<br />this.AllProducts.Add(new Product { ProductId = 5, ProductName = "Grape" }); <br />this.AllProducts.Add(new Product { ProductId = 6, ProductName = "Grapefruit" });<br />this.AllProducts.Add(new Product { ProductId = 7, ProductName = "Strawberry" })<br />this.AllProducts.Add(new Product { ProductId = 8, ProductName = "Melon" });<br />this.AllProducts.Add(new Product { ProductId = 9, ProductName = "Guava" });<br />this.AllProducts.Add(new Product { ProductId = 10, ProductName = "Kiwi" });<br />this.AllProducts.Add(new Product { ProductId = 11, ProductName = "Pineapple" });<br />this.AllProducts.Add(new Product { ProductId = 12, ProductName = "Mango" });<br />LoadProductsCommand= new DelegateCommand(LoadProducts, CanLoadProducts); <br /> } <br /> private void LoadProducts(object param) <br />{<br /> string filter = param as string ?? string.Empty; <br />this.Products.Clear();<br />varquery = from p in this.AllProducts<br /> where p.ProductName.ToLower().StartsWith(filter.ToLower())<br /> select p;<br />foreach(var item in query) { <br />this.Products.Add(item);<br /> }<br />} <br /> private boolCanLoadProducts(object param) { return true } <br /> public ICommandLoadProductsCommand { get; set; } <br />public ObservableCollection<Product> AllProducts { get; set; } <br />private ObservableCollection<Product> products; <br /> public ObservableCollection<Product> Products { <br /> get<br /> { <br /> return products<br /> }<br /> set<br /> { products = value;<br />this.FirePropertyChanged("Product");<br /> } <br />} <br />}<br />
    39. 39. Commanding 実装のための5つのステップ –ViewModel Base<br />public abstract class ViewModelBase : INotifyPropertyChanged<br />{<br />public ViewModelBase()<br />{<br />}<br />public event PropertyChangedEventHandlerPropertyChanged; <br /> protected void FirePropertyChanged(string propertyname) <br />{<br />varhandler = PropertyChanged; <br /> if (handler != null) <br /> handler<br /> (this, new PropertyChangedEventArgs(propertyname));<br />}<br />}<br />
    40. 40. Event Aggregatorパブリッシャとサブスクライバ<br />色々な種類のイベントをパブリッシュ及びサブスクライブ可能にする<br />クロスモジュール化可能<br />サブスクライバによるフィルタリング可能<br />例えば:<br />Shell の中のMenu アイテム上をクリック<br />イベントはパブリッシャから呼び出される<br />イベントはサブスクライバに受信される<br />それにより、当該サブスクライバは、 Shell の中の、ある Region の中の、一つのViewをロードする<br />
    41. 41. Infrastructure共通のTools<br />Infrastructure は、Silverlight class library プロジェクト<br />クラス、アセット、リソースを含み、モジュール間で共有される<br />他のモジュールを参照してはならない<br />Web サービスをコールしてはならない<br />純粋なライブラリ<br />
    42. 42. Modular MVVM and Prism<br />demo <br />
    43. 43. Screen Presentation EnablerScreensを生成する<br />スクリーン間をナビゲート可能にしなければならない<br />View 同志はお互いのことを知らない<br />独自のScreen Conductor を作成可能<br />Loading / Unloading<br />Displaying / Hiding<br />そのまま終了して良いですか?<br />自分でクリーンアップしましょう!<br />
    44. 44. Screen Presentation FrameworkKey Players<br />Screen<br />MVVM トライアドを管理<br />ScreenFactory<br />Screen class を作成<br />ScreenFactoryRegistry<br />ScreenFactoryディレクトリ<br />ScreenConductor<br />Screen のアクティベーションイベントをリッスンしたり、その上で動いたりする<br />ScreenCollection<br />Screensを収集する<br />
    45. 45. Screen Conductor<br />demo <br />
    46. 46. 参考情報その他Blog、チュートリアル、サンプル、等々<br />Introducing the Earthquake Locator – A Bing Maps Silverlight Application, part 1 <br />http://geekswithblogs.net/bdiaz/archive/2010/03/06/introducing-the-earthquake-locator--a-bing-maps-silverlight-application.aspx <br />MVVM Light Toolkit<br />http://www.galasoft.ch/mvvm/getstarted/<br />Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 25: ViewModel<br />http://blogs.msdn.com/brada/archive/2009/09/07/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-viewmodel.aspx<br />ViewModel Pattern in Silverlight using Behaviors<br />http://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx<br />Simple Step for Commanding in Silverlight <br />http://devlicio.us/blogs/christopher_bennage/archive/2010/03/03/1-simple-step-for-commanding-in-silverlight.aspx<br />

    ×