Building Silverlight Large Scale Application Using MVVM

Post on 28-May-2015

2.112 views 3 download

description

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

Transcript of Building Silverlight Large Scale Application Using MVVM

Silverlight を使ったLarge-Scale Application の構築- MVVM 及び Prism のご紹介 -

鈴木 章太郎アーキテクトエバンジェリストマイクロソフト株式会社http://blogs.msdn.com/shosuz/ Twitter : @shosuz

アウトライン

MVVMModel – View – ViewModel何をするものかどこで使えば一番うまく使えるか応用

PrismMVVM を有効に使うためにギャップを埋めるためにオプション

ゴール

Silverlight における MVVM の重要性ゴールを達成するためには多くの手段がある

実際に動かしてみよう

MVVM イネーブラについて学ぼうPrism独自のものを作成しよう

他にも MV_ とついているものが… ?

MVVMMVCMVPMV????

アプリケーション構築において、メンテナンス性やスケーラビリティ確保のために、一般的に受け入れられているパターン

Model-View-ViewModel 全体像MVVM, Prism, MEF - WCF RIA Services 連携

WPF 、 Silverlight の疎結合 ソリューションのパターン下記の実装を行う ( トライアド )

Model Data(Web)Service のエンティティ( をラップする )WCF RIA Services を Model と することも可能

ViewModel Model を UI に合わせて公開する

View ViewModel を XAML 等でバインドする

参照: http://msdn.microsoft.com/ja-jp/magazine/dd458800.aspx

MVVMどんなものか?なぜ必要か?

関心の分離View = UI を担当Model = 純粋なデータを含むViewModel = バインディングを通じたView と Model との間のコミュニケーションSilverlight と WPF とで有効活用可能

XAML ベースのデータバインディングテスト可能

MVVMどんなものか?なぜ必要か?

Model : INotifyPropertyChanged 、 IDataErrorInfo を実装しているクラス (UI 要素は持たず、 Setter/Getter としてのプロパティを持つのみ )

ViewModel が取り扱うデータを保持するものViewModel : INotifyPropertyChanged を実装しているクラス (UI 要素は持たず、ビジネスロジックやサーバーとの通信を担当する )

多くは ObservableCollection として View にバインドするデータ(Model) を取得し、保持するもの分離コードで Command とイベントハンドラ (Command Receiver) の対応付けを行うExpression Blend のオブジェクトデータソースとしてスタティックリソース宣言が可能(ドラッグ&ドロップで UI 構築)

 View :XAML による UserControl (UI 要素のみ )ViewModel から提供されるデータ (Model) を 2-ways データバインドにより表示・更新するXAML 側で Command の宣言を行うできれば分離コードを一切もたない dumb コントロールとしての実装が望ましい (ViewModel の割り当てを View の分離コードで実行することもできるが、 View – ViewModel の分離が不明確になる可能性がある )

The MVVM のトライアドすべてを一緒に

コントロールにデータを表示

UI フレンドリーなエンティティや、 UI 状態、アクション

データを表すエンティティ

ViewModel

View

Model

ModelMVVM

データを表すエンティティどこから取得したデータかは知る必要なし

WCF サービス、 WCF RIA Services 等々バリデーションを含む場合あり

ViewMVVM

画面 , UI, Silverlight の UserControl UI のルック & フィールを担当情報を表示バインディングを通じて、 ViewModel とコミュニケート

ViewModelMVVM

MVVM トライアドのためのロジックのメインソースModel を View と接続するView を抽象化するView にバインドされた Public プロパティINotifyPropertyChanged と、 INotifyCollectionChanged とによる、バインディングを通じた View との会話バインディングを通じた View からの変更の通知 MVVM トライアドの外部とのコミュニケートのためのサービスの呼び出し

MVVM はどこから始めるのが良いか ?MVVM バリエーション

View は ViewModel と何らかの関連性を持つ幾つかの実施可能なオプション

View FirstView Model First

MVVM トライアドの個々のパーツのメンテナンス

View First MVVM Variations

ViewModel は View の XAML の中のスタティックなリソースとして宣言される

Expression Blend で作れる

もう一つの方法としては、 ViewModel を View の分離コードで作成する

DEMO

View First MVVM

demo

ViewModel FirstMVVM バリエーション

View は、 ViewModel のコンストラクタにインジェクト ( =注入 ) される

Example:View が Dependency Injection を使って作成されると、 ViewModel が 作成される

View と ViewModel との結び付けMVVM バリエーション

View は ViewModel と何らかの形で一対になるViewModel と View は一旦作成され、中間段階を経て、その後一対となる

View と ViewModel との結び付け

vm = new MyVM();view = new MyView();view.DataContext = vm;

// With Unityvm = container.Resolve<IMyVM>();view = container.Resolve<MyView>();

view.DataContext = vm;

Prism についていつでも選択可能

Prism は、オプションのセット使いたいものだけを選んで使い、残りは無視して良し

例 : モジュールとコマンドは選ぶが、イベントアグリゲーションとリージョンは無視する

Prism: patterns & practices Composite Application Guidance for WPF and Silverlight site

http://www.codeplex.com/CompositeWPF

Prism の技術コンセプト

Container

Commands

Bootstrapper

Regions

Modules

Event Aggregation

Unity and DI

Shell

Bootstrapperスタートするための機能

アプリケーションを起動メイン UI コンテナをスタート (Shell)(必要に応じて)モジュールの登録とロードグローバルシングルトンの登録 ( オプション )通常 “ Bootstrapper プロジェクト” に含まれる

Shellメイン View

メイン UI コンテナロードされ得るすべての View をホストリージョンに分割可能Shell 自身は、その中に何がロードされるかを知らない

RegionsContent エリア

View を配置できる Shell の中のエリア名前を付ける必要ありコンテキストを内包可能 ( オプション )RegionManager により Region をメンテナンス可能

ModularitySelf Contained Modules

ユーザーにとってはシームレス分割して開発される他のモジュールを参照してはならないSolution は Modules に分割されるExample:

City government applicationModule 1: Managing land parcelsModule 2: Traffic light administrationModule 4: City Parks

Modules は、 infrastructure と Models  をシェアする

Dependency InjectionUnity の利用

Unity 又は他の DI ツール群 ( 例 :Ninject)テスト可能でモック作成抽象化コンテナオブジェクトにより、クラスがそのインターフェースに従って登録されるインターフェースをリクエストされたとき、コンテナは、当該インターフェースと一緒に登録されたクラスを、作成するシングルトンのサポート

クラスへのインターフェースの登録

container.RegisterType<IMyViewModel,

MyViewModel>();

コンクリート Class の作成

container.Resolve<IMyViewModel>();

Infrastructure共通の Tools

Silverlight クラスライブラリプロジェクトモジュールのために共有可能なアイテムを含む

ClassesAssetsResources

何の参照も作成しない純粋なライブラリ

Commandingアクションとリアクション

データバインディングを通じた View と ViewModel との間のイベントを許可ViewModel が宣言するのは Command receiverCommand は XAML の中で宣言される

Button - ClickListBox (Selector) – Selected

Command は、 ViewModel の Command receiver にデータバインドされるルールベースで disabled/enabled 設定可能

Commanding 実装のための5 つのステップ – 前提

Silverlight 4 プロジェクトにおける ICommand 実装は、数ステップで足りる問い合わせの多い個所なので、下記にCommanding 実装のためのシンプルなテクニックを記述する

Commanding 実装のための 5つのステップ – ICommand の実装最初のステップは、 ICommand インターフェースクラスの実装

このクラスは Commanding アスペクトを管理する他にも色々オプションがあるところ、ここではシンプルな ICommand の実装方法を紹介

当該 DelegatedCommand クラスで実装するのは、 ICommand の CanExecute メソッド、Execute メソッド、そして、 CaneExecuteChanged イベントこのコードはそのままコピー &ペーストして利用可能

Commanding 実装のための 5 つのステップ – ICommand の実装 ① public class DelegateCommand : ICommand { Func<object, bool> canExecute; Action<object> executeAction; bool canExecuteCache; public DelegateCommand(Action<object> executeAction, Func<object, bool>canExecute) {

this.executeAction = executeAction; this.canExecute = canExecute; } …

Commanding 実装のための 5 つのステップ – ICommand の実装 ②#region ICommand Members

public bool CanExecute(object parameter) { bool temp = canExecute(parameter); if (canExecuteCache != temp) { canExecuteCache = temp; if (CanExecuteChanged != null) { CanExecuteChanged(this, new

EventArgs()); } } return canExecuteCache; }

Commanding 実装のための 5 つのステップ – ICommand の実装 ②

・・・続き・・・public event EventHandler

CanExecuteChanged; public void Execute(object parameter) { executeAction(parameter); }#endregion}

Commanding 実装のための 5 つのステップ – Command の定義

//ICommand を表示するための Public プロパティ を ViewModel に追加// このプロパティは 、通常は、ボタン等により、   View にバインドされる

public ICommand LoadProductsCommand { get;

set; }

Commanding 実装のための 5 つのステップ – Command の作成

//ViewModel のコンストラクタの中で、  1 で作成したコマンドプロパティを設定する

LoadProductsCommand =   new DelegateCommand

  (LoadProducts, CanLoadProducts);

Commanding 実装のための 5 つのステップ – ViewModel の作成// ViewModel が View からアクセス可能なこと を確認する// 様々な方法があるところ、シンプルに View

の XAML 中の Static Resource として作成

<UserControl.Resources> <local:ProductViewModel

x:Key="vm"/></UserControl.Resources>

Commanding 実装のための 5 つのステップ – Command のバインド//ボタンコントロールを追加し、当該コマンドプロパティを ViewModel の中で作ったコマンドにバインドする// 当該 Command に parameter を渡したい場合には、 CommandParameter プロパティを、当該 View の中の要素にバインド できる ( 通常は parameter は必要ないが、例として実装 )

<Button Content="Load" Width="120" Command="{Binding

LoadProductsCommand}" CommandParameter= "{Binding ElementName=

FilterTextBox, Path=Text}" />

Commanding 実装のための 5 つのステップ – ProductViewModel 完成品 public class ProductViewModel : ViewModelBase

{ public ProductViewModel(){

this.Products = new ObservableCollection<Product>(); this.AllProducts = new ObservableCollection<Product>();this.AllProducts.Add(new Product { ProductId = 1, ProductName = "Apple" });

this.AllProducts.Add(new Product { ProductId = 2, ProductName = "Orange" });this.AllProducts.Add(new Product { ProductId = 3, ProductName = "Banana" }); this.AllProducts.Add(new Product { ProductId = 4, ProductName = "Pear" })this.AllProducts.Add(new Product { ProductId = 5, ProductName = "Grape" }); this.AllProducts.Add(new Product { ProductId = 6, ProductName = "Grapefruit" });this.AllProducts.Add(new Product { ProductId = 7, ProductName = "Strawberry" })this.AllProducts.Add(new Product { ProductId = 8, ProductName = "Melon" });this.AllProducts.Add(new Product { ProductId = 9, ProductName = "Guava" });this.AllProducts.Add(new Product { ProductId = 10, ProductName = "Kiwi" });this.AllProducts.Add(new Product { ProductId = 11, ProductName = "Pineapple" });this.AllProducts.Add(new Product { ProductId = 12, ProductName = "Mango" });

LoadProductsCommand = new DelegateCommand(LoadProducts, CanLoadProducts); } private void LoadProducts(object param) {

string filter = param as string ?? string.Empty; this.Products.Clear();var query = from p in this.AllProductswhere p.ProductName.ToLower().StartsWith(filter.ToLower())select p;foreach (var item in query) {

this.Products.Add(item);}

} private bool CanLoadProducts(object param) { return true   } public ICommand LoadProductsCommand { get; set; } public ObservableCollection<Product> AllProducts { get; set; } private ObservableCollection<Product> products; public ObservableCollection<Product> Products {

get{

return products}set{ products = value;

this.FirePropertyChanged("Product");}

} }

Commanding 実装のための 5 つのステップ – ViewModel Basepublic abstract class ViewModelBase : INotifyPropertyChanged{

public ViewModelBase(){}

public event PropertyChangedEventHandler PropertyChanged;

protected void FirePropertyChanged(string propertyname) {

var handler = PropertyChanged; if (handler != null)

handler  (this, new

PropertyChangedEventArgs(propertyname));}

}

Event Aggregatorパブリッシャとサブスクライバ

色々な種類のイベントをパブリッシュ及びサブスクライブ可能にするクロスモジュール化可能サブスクライバによるフィルタリング可能例えば :

1. Shell の中の Menu アイテム上をクリック2. イベントはパブリッシャから呼び出される3. イベントはサブスクライバに受信される4. それにより、当該サブスクライバは、

Shell の中の、ある Region の中の、一つの View をロードする

Infrastructure共通の Tools

Infrastructure は、 Silverlight class library プロジェクトクラス、アセット、リソースを含み、モジュール間で共有される他のモジュールを参照してはならないWeb サービスをコールしてはならない純粋なライブラリ

DEMO

Modular MVVM and Prism

demo

Screen Presentation EnablerScreens を生成する

スクリーン間をナビゲート可能にしなければならないView 同志はお互いのことを知らない独自の Screen Conductor を作成可能

Loading / UnloadingDisplaying / Hidingそのまま終了して良いですか ?自分でクリーンアップしましょう !

Screen Presentation FrameworkKey Players

ScreenMVVM トライアドを管理

ScreenFactoryScreen class を作成

ScreenFactoryRegistryScreenFactory ディレクトリ

ScreenConductorScreen のアクティベーションイベントをリッスンしたり、その上で動いたりする

ScreenCollectionScreens を収集する

DEMO

Screen Conductor

demo

参考情報その他Blog 、チュートリアル、サンプル、等々

Introducing the Earthquake Locator – A Bing Maps Silverlight Application, part 1

http://geekswithblogs.net/bdiaz/archive/2010/03/06/introducing-the-earthquake-locator--a-bing-maps-silverlight-application.aspx  

MVVM Light Toolkithttp://www.galasoft.ch/mvvm/getstarted/

Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 25: ViewModel

http://blogs.msdn.com/brada/archive/2009/09/07/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-viewmodel.aspx

ViewModel Pattern in Silverlight using Behaviorshttp://www.nikhilk.net/Silverlight-ViewModel-Pattern.aspx

Simple Step for Commanding in Silverlight http://devlicio.us/blogs/christopher_bennage/archive/2010/03/03/1-simple-step-for-commanding-in-silverlight.aspx

© 2010 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.