MVVM Design Pattern NDC2009

Preview:

DESCRIPTION

Presentation on the Model-View-ViewModel Design Pattern for Silverlight application. Presented by Jonas Follesø at the Norwegian Developer Conference 2009.

Citation preview

1

Model-View-ViewModel and friends…

Jonas FollesøSenior ConsultantCapgemini

2

3

Agenda

MVVM IntoMVVM and DISupporting Patterns

CommandEvent AggregatorService Locator

Q&A

4

Dive Log App

5

Dive Log Application

demo

6

Everything in code behind…is probably not a good idea

7

A team of sad coders and designers

FAIL!

8

Lasagna

FTW!

10

Different people reading about MVC in different places take different ideas from it and describe these as “MVC”.

Martin Fowler, GUI Architectures Essay (July 2006)

11Separated Presentation Patterns

12

Data & Domain Logic(Model)

UI(View)

Interaction (Controller/Presenter)

13

Presentation Model is of a fully self-contained class that represents all the data and behavior of the UI, but without any of the controls used to render that UI on the screen. A view then simply projects the state of the presentation model onto the glass.

Martin Fowler, Presentation Model Essay, July 2004

14

The most annoying part of Presentation Model is the synchronization between Presentation Model and view…

Martin Fowler, GUI Architectures Essay, July 2004

15

Ideally some kind of framework could handle this, which I'm hoping will happen some day with technologies like .NET's data binding.

Martin Fowler, Presentation Model Essay, July 2004

16

Everything in code-behind

Data Model

View

XAML

Code-BehindEvent Handlers

17

Model – View – ViewModel

Data Model

View

XAML

Code-Behind

View Model

State + Operations

Change notification

Data-binding and commands

18

Data BindingImplement INotifyPropertyChanged and use ObservableCollection<T> for collections

View <ListBox ItemsSource="{Binding Path=Dives}" SelectedItem="{Binding Path=SelectedDive, Mode=TwoWay}" />

View Model

State + Operations

19

Data BindingImplement INotifyPropertyChanged and use ObservableCollection<T> for collections

View

XAML

Code-Behind

View Modelpublic class DiveViewModel : INotifyPropertyChanged{ public event PropertyChangedEventHandler PropertyChanged; public ObservableCollection<Dive> Dives { ... } public Dive SelectedDive { ... }}

21

A simple View Model

demo

22

“Once a developer becomes comfortable with WPF and MVVM, it can be difficult to differentiate the two.”

Josh Smith, WPF Apps With The Model-View-ViewModel Design Pattern

23

“MVVM is the lingua franca of WPF developers because it is well suited to the WPF platform, and WPF was designed to make it easy to build applications using the MVVM pattern”

Josh Smith, WPF Apps With The Model-View-ViewModel Design Pattern

24

User Interaction

But what about Word?

Viewprivate void btnSave_Clicked(object sender, ExecutedEventArgs e){ ((PageViewModel)DataContext).Save();}

25

Objects are used to represent actions. A command object encapsulates an action and its parameters.

This allows a decoupling of the invoker of the command and the handlers of the command.

26

Command Pattern

public interface ICommand{

event EventHandler CanExecuteChanged;

bool CanExecute(object parameter);void Execute(object parameter);

}

27

Commands in SilverlightView

<Button Content=“Delete Dive” commands:Click.CommandParameter=“{Binding}” commands:Click.Command=“DeleteCommand” />

View Modelprivate ICommand DeleteCommand { get; private set; }

public PageViewModel(){ DeleteCommand = new DelegateCommand<Dive>(DeleteDive);}

private void DeleteDive(Dive dive){ // code to save dives..}

28

Commands

demo

30

Dealing with dependencies

The View Model is coupled with the web service.

Makes code less flexible for changeMakes code harder to test

Object should not be responsible for creating their own dependencies – Inversion of Control

31

Dependency Injection (DI)

One form of Inversion of Control (IoC) Create dependencies outside the object and, inject them into it

But who creates the dependency?

Presentation Modelpublic PageViewModel(IDiveLogServiceClient proxy){ this.proxy = proxy}

32

Dependency Injection by hand

Should the page be responsible for creating dependencies?

Viewpublic Page(){ InitializeComponent(); if (HtmlPage.IsEnabled) this.DataContext = new PageViewModel(new DiveLogServiceClient()); else this.DataContext = new PageViewModel(new ServiceStub());}

33

IoC Containers

View Model

public PageViewModel(IDiveLogServiceClient proxy){ this.proxy = proxy}

Viewpublic Page(){ InitializeComponent(); IKernel iocContainer = new StandardKernel(); this.DataContext = iocContainer.Get<PageViewModel>();}

34

Who came first?

35

View Model First

The ViewModel creates the view (usually through an IoC container).

View Model

public MyViewModel(IMyView myView){

myView.Model = this;}

36

View First

The View has a relationship to its ViewModel (usually through data binding).

View<UserControl.DataContext> <dive:PageViewModel /></UserControl.DataContext>

Available at design time (Blend support)Need to find a way to use IoC and set DataContext declaratively…

37

Using DI on the ViewModel

demo

38

View Model Communication?

View Model

View Model

View Model View Model

View Model

View Model

View Model View Model

FAIL!

39

It’s all about coupling…

40

... or how to decouple…

41

Event Aggregator

View Model

View Model

View Model View Model

View Model

View Model

View Model View Model

42

Event Aggregator

View Model

View Model

View Model View Model

View Model

View Model

View Model View Model

Event Aggregator

43

View Model Communication

Data Model

View

XAML

Code-Behind

Data Model

View

XAML

Code-Behind

Message

View Model

State + OperationsView Model

State + Operations

View

XAML

Code-Behind

MessageEvent AggregatorView Model

State + Operations

Publish messages

Subscribe to messages

44

ViewModel communication using Event Aggregator

demo

45

MVVM Cheat Sheet

Put State and Behaviour in View Model

Invoke Operations using Commands

Cross View Model communication through Mediator/Event Aggregator

Service Locator to bind View to View Model (View first)

46

SummarySeperated Presentation Decoupling

47

Q & A

48

Photo Copyright Notices

All diving photos taken by Hege Røkenes and licensed under the creative commons license. http://flickr.com/photos/hegerokenes/

Photos of Martin Fowler taken by Dave Thomas and licensed under the creative commons license.http://flickr.com/photos/pragdave/

Recommended