03 | model-view-viewmodeldownload.microsoft.com/download/f/5/8/f58708ee-c449-4ff3...mvvm is a...
TRANSCRIPT
03 | Model-View-ViewModel
Ben Riga
http://about.me/ben.riga
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
Course Topics
Model-View-ViewModel
Introduction to MVVM (Model-View-ViewModel)
Architecture
Pros and cons
Sharing code using MVVM
.NET portable class library
Best practices
Agenda
MVVM libraries
MVVM Light Toolkit
Q&A
Introduction to 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 Overview: What is MVVM?
Architecture
View
ViewModel
Commands Data
Binding
Events
/Messages
View
ViewModel Messages,
Callbacks
Model
Not every app should use MVVM…
Weigh the pros and cons and decide the best approach for your scenario
Pros and Cons
Pros
Can reuse Model and View-Model code across platforms
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
Cons
Lots of boilerplate code
May be more powerful than necessary for certain apps
Decoupling loses strong type checking
Sharing Code using
MVVM
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
MVVM and Code Sharing
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
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);
}
}
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
View
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
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;
});
}
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.
About the Demo
Shared
PhotoManager.Core.Win8 PhotoManager.Core.WP8
PhotoManager.WP8 PhotoManager.Win8
Demo: MVVM
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
Data Binding
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
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
Commands
<Button Command="{Binding AddCommand}"
CommandParameter="Untitled" Content="Button"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
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);
}
}
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
Messages public interface IMessenger
{
void
Subscribe<TMessage>(Action<TMessage>
handler);
void
Unsubscribe<TMessage>(Action<TMessage>
handler);
void Publish<TMessage>(TMessage
message);
}
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);
}
// ...
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!" });
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
.NET Portable Class Library
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 code-behind 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 binding’s 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.
Best Practices
MVVM Libraries
Numerous Tools Available
Source: Wikipedia Jan, 2013
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
MVVM Light Toolkit
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
Recap
Q&A