You are on page 1of 35

03 | Model-View-ViewModel

Ben Riga http://about.me/ben.riga

Course Topics
Building Apps for Both Windows 8 and Windows Phone 8 Jump Start 01 | Comparing Windows 8 and Windows Phone 8 02 | Basics of View Models 03 | MVVM ( (Model-View-ViewModel) 04 | Sharing Code

Model-View-ViewModel

Agenda
Introduction to MVVM (ModelView-ViewModel)
Architecture
Pros and cons

MVVM libraries
MVVM Light Toolkit

Q&A

Sharing code using MVVM


.NET portable class library Best practices

Introduction to MVVM

Architecture Overview: What is MVVM?


MVVM is a software architectural pattern
Like many patterns, it promotes code reuse through separations of concerns and modularity

An MVVM app is divided into three main parts:


The Model stores and maintains the program data The View presents data and receives user-input through a platform-customized UI and UX The ViewModel presents an interface to bind data to Views

Each part is very loosely coupled


Reuse the Model and the ViewModel across platforms, but not the View

Architecture
View
Data Binding
Commands

View
Events /Messages

ViewModel

Messages, Callbacks

ViewModel

Model

Pros and Cons


Not every app should use MVVM
Weigh the pros and cons and decide the best approach for your scenario

Pros
Can reuse Model and View-Model code across platforms

Cons
Lots of boilerplate code May be more powerful than necessary for certain apps Decoupling loses strong type checking

Code has a clearly defined structure


Test the ViewModel with unit tests Maintainability

Can show design-time data in Expression Blend and the Visual Studio designer

Sharing Code using MVVM

MVVM and Code Sharing


This section looks at some of the details of MVVM
Also, a look at the portable class library

Finally, some best practices when using MVVM

Includes an overview of each part of MVVM


Model, View, and ViewModel

Emphasis on those parts that facilitate code sharing


Data Binding

Commands
Messages

Model
The Model, or the Data Model, stores the persistent data for an app
Can be databases, local storage files, settings, or any other persistent data

Responsible for create, retrieve, update, and delete operations

Model should know nothing about the View or ViewModel Usually the most portable part of the app Windows Phone 8 supports a local SQL Server CE database
Windows 8 does not, but SQLite libraries are readily available

Model
public class CommonDataItem { public DataItem(string uid) { Uid = uid; } public string Uid { get; private set; } // Other properties ... } public interface IDataService { void GetItem(Action<CommonDataItem> callback, string uid); } public class DataService : IDataService { public void GetItem(Action<CommonDataItem> callback, string uid) { // Retrieve the data from the actual source // ... var item = new DataItem(...); callback(item); } }

View
A View should present the user with an interface to see and manipulate the data
An app can have many Views Views are defined by XAML

Data binding connects Views to ViewModels


Still possible to manually listen for changes and update the Views and the Model from the code-behind
- Not the best way to keep a View up-to-date

In MVVM, the View does not handle user actions


That is the responsibility of the ViewModel

ViewModel
A ViewModel, or PresentationModel, is responsible for:
Presenting data to the view Responding to user manipulations of the view

Data binding can relieve the work of updating the view The ViewModel holds the business logic of the app Decoupled from the View
Lets developers work on the ViewModel while designers work on the View

ViewModel
An app can have many ViewModels

Usually a one-to-one correspondence between Views and ViewModels A ViewModel is linked to a View by setting the DataContext property for an element in the View
This binding is inherited by all child elements

ViewModel
public class MainViewModel : ViewModelBase { private readonly IDataService _dataService; public const string Title_PropertyName = "Title"; private string _title = string.Empty; public string Title { get { return _title; } set { if (_title == value) return; _title = value; RaisePropertyChanged(Title_PropertyName); } } // Constructor... } public MainViewModel(IDataService dataService) { _dataService = dataService; _dataService.GetData( (item) => { Title = item.Title; }); }

About the Demo


The demo for this presentation uses the PhotoManager app.
It showcases MVVM well. The PhotoManager will also be used for demos in the next presentation.

PhotoManager.Win8 PhotoManager.Core.Win8

PhotoManager.WP8 PhotoManager.Core.WP8

Shared

Demo: MVVM

Data Binding
Data binding is critical to the MVVM pattern

Links the View to the ViewModel


Can be a one-time, one-way, or two-way link

Advantages:
Write less code to update the view Easier to unit test Loose coupling avoids crashing the app Can provide design-time data for the designer

Commands
In MVVM, commands let the View tell the ViewModel to execute code in response to a user action
Replaces the paradigm of registering for events in the View. Implement System.Windows.Input.ICommand interface Commands can be enabled and disabled - Raise the CanExecuteChanged event when this happens

Commands
class AddItemCommand : ICommand { ViewModel _viewModel; public AddItemCommand(ViewModel viewModel) { _viewModel = viewModel; } public event EventHandler CanExecuteChanged; public bool CanExecute(object parameter) { return true; } public void Execute(object title) { _viewModel.AddItem(title as string); } }

In the XAML snippet, make sure that the DataContext is set to an instance of the ViewModel class. The ViewModel class exposes an AddCommand property of type AddItemCommand The ViewModel is responsible for actually adding a new item

<Button Command="{Binding AddCommand}" CommandParameter="Untitled" Content="Button" HorizontalAlignment="Center" VerticalAlignment="Center"/>

Messages
Messages are a way to send information between objects.
Sender and receiver Useful for communication between ViewModels Often a callback for when the receiver is done handling a message No built-in APIs, but some MVVM libraries provide support

Why send messages?


Suppose two ViewModels are attached to a single view - Each ViewModel handles a part of the view You want actions received by one ViewModel to be passed to another

Messages
public abstract class BaseViewModel : INotifyPropertyChanged { private IMessenger _messenger; public IMessenger Messenger { get { return _messenger; } set { if (_messenger != null) Unsubscribe(); _messenger = value; Subscribe(); } } protected virtual void Unsubscribe() { } protected virtual void Subscribe() { } protected void PublishMessage<TMessage>(TMessage message) { if (Messenger != null) Messenger.Publish<TMessage>(message); } // ...

public interface IMessenger { void Subscribe<TMessage>(Action<TMessage> handler); void Unsubscribe<TMessage>(Action<TMessage> handler); void Publish<TMessage>(TMessage message); }

Messages
public class MessageRecipient { public MessageRecipient() { Messenger.Default.Register<MyMessage>(this, async (msg) => { var dlg = new MessageDialog(msg.Content); await dlg.ShowAsync(); }); } } public class MyMessage : MessageBase { public string Content { get; set; } }

var _recipient = new MessageRecipient(); // ... Messenger.Default.Send<MyMessage>(new MyMessage() { Content = "Hello World!" });

.NET Portable Class Library


Visual Studio 2012 provides a portable class library template
Only cross-platform .NET APIs available Compiles into a separate library (.dll) Only managed code Only available in non-express editions of Visual Studio 2012

Best Practices
Design apps for cross-platform portability
Use MVVM to help achieve this

Keep the components of an app loosely coupled


Separation of concerns

- Each component has a single well-defined role


Avoid dependencies between Model, View, ViewModel

Plan for upgrades, redesigns, and testing


Again, consider MVVM or another loosely coupled architecture

Best Practices
Data binding should eliminate a lot of the code in the codebehind file
Some code-behind is OK, but look for ways to use data-binding and commands to replace this code.

Avoid binding the same large collection multiple times on the same XAML page
This applies to pivots as well. Avoid duplicate bindings to different pivot pages that are part of the same pivot.

Binding does incur both memory and CPU overhead, so be careful how much data is bound to a page.

Best Practices
Large collections bound to list controls should be virtualized
You can use the VirtualizingStackPanel in place of the StackPanel

You can narrow the scope of the bindings data context within the XAML document. For example:
A Car object exposes an Engine object through a property named CarEngine A Car exposed by the MyCar property (of the View Model) is the data context for a XAML element Child elements of that XAML element can change their data context to the CarEngine by setting it to MyCar.CarEngine.

This helps avoid long property paths.

MVVM Libraries

Numerous Tools Available

Source: Wikipedia Jan, 2013

MVVM Light Toolkit


Open-source framework created and maintained by GalaSoft
Library includes Visual Studio templates Download at: http://mvvmlight.codeplex.com/

Supports a light-weight implementation of the MVVM pattern


Suitable for medium-large projects

Two parts to the library


Essentials: RelayCommand, Messenger, ViewModelBase Extras: EventToCommand, DispatcherHelper

Recap

Recap
MVVM means Model-View-ViewModel
The Model stores the persistent data

The View presents the user with an interface to view and manipulate data
A ViewModel presents data to the view and responds to user actions

MVVM is a useful pattern for Windows Phone 8 (and Windows 8) that lets you reuse much of your app business logic
Avoid causing chaos in the ViewModel when you replace the View

MVVM works well with other cross-platform code reuse strategies:


Portable libraries, inheritance, partial classes, shared code files, #if blocks

Q&A

You might also like