Académique Documents
Professionnel Documents
Culture Documents
John Cumming
Senior Engineer CM Group Ltd http://www.cmgroup.co.uk http://sputnikdev.wordpress.com
Overview
A bit about my experience of MVVM. What problems adopting MVVM addresses. An overview of the MVVM pattern. Adopting MVVM. A simple example.
About me
MVVM
Tightly coupled brittle code that is difficult to maintain and extend. It can be difficult to separate UI state and logic from the UI presentation. Difficult to test UI state and logic. The designer is tied to the UI components written by the developer.
Separation of Concerns
View UI Layout & User Interaction View Model UI State and Logic Model Business Logic and Data
Data Binding DataContext Data Binding Dependency Properties Commands Executing Actions & Operations
Increased Testability
Designer has freedom to design. Designer can work independently. Designer does not need to touch code. Designer can create design time sample data.
MVVM OVERVIEW
MVVM View
The View defines the structure and appearance of the UI. The Views DataContext is a View Model. Minimal, if any, code behind. View updated by notification events from the View Model. UI Gestures are passed to the View Model, usually via Commands.
The View Model is responsible for UI logic, data and state. The View Model exposes bindable properties. The View Model exposes ICommand properties for UI controls with Command properties. The View Model exposes public methods that can be invoked by the View. The View Model is completely testable.
MVVM Model
The Model is responsible for business logic and data, the client side Domain Model. The Model can expose bindable properties for use by the View directly or via the View Model as an Adapter. Model objects can implement IDataErrorInfo to provide the View with validation state information.
MVVM Commands
Invoked in the View by user interaction. Bound to ICommand properties in the View Model. Differ from WPF Routed Commands as they are not delivered via the UI logical tree. Equally, Routed Commands will not get delivered to the View Model as it is outside the UI logical tree.
Implement IDataErrorInfo or INotifyDataErrorInfo in View Model and Model classes. IDataErrorInfo presents basic indexed error information. INotifyDataErrorInfo presents multiple errors per property, asynchronous data validation and notification of error state changes (In WPF 4/ Silverlight 4).
ADOPTING MVVM
Order of Construction
Dependency Injection
Code.
Uses d:DataContext and d:DesignInstance XAML markup extensions. May need to be maintained by developers.
Key Decisions
Construct Views or View Models first and use of a dependency injection container. Expose Commands from the View Model as Command objects or Command methods. Use of IDataErrorInfo / INotifyDataErrorInfo. Provision of design time data for use in Expression Blend.
AN MVVM EXAMPLE
Pre MVVM
Bootstrapping StartupUri for App
<Application x:Class="WpfMediaPlayer.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" StartupUri="MainWindow.xaml">
MVVM
Bootstrapping Dependency Injection Separate View Components in UI
<<View>> NowPlayingView
<<ViewModel>> ISelectedDirectoryViewModel
Commands: + ICommand OpenCommand Properties: + String DirectoryPath
<<ViewModel>> INowPlayingViewModel
Commands: + ICommand PauseResumeCommand Properties: +
<<View>> NowPlayingView
Model Components
<<View>> MediaListView
<<Model>> MediaFile MediaFolder MediaPlayer
<<View>> SelectedDirectoryView
<<ViewModel>> IMediaListViewModel
Commands: + ICommand PlayCommand Properties: + ObsCol<IMediaFile> MediaFiles
IMediaFile IMediaFolder
<<ViewModel>> ISelectedDirectoryViewModel
Commands: + ICommand OpenCommand Properties: + String DirectoryPath
<<ViewModel>> INowPlayingViewModel
Commands: + ICommand PauseResumeCommand Properties: +
<<View>> NowPlayingView
MVVM Bootstrapping
App.xaml.cs
protected override void OnStartup(StartupEventArgs e) { using (IUnityContainer container = new UnityContainer()) { // register models container.RegisterType<IMediaFolder, MediaFolder> (new ContainerControlledLifetimeManager()); // register view models container.RegisterType<ISelectedDirectoryViewModel, SelectedDirectoryViewModel> (new ContainerControlledLifetimeManager()); container.RegisterType<IMediaListViewModel, MediaListViewModel> (new ContainerControlledLifetimeManager()); container.RegisterType<INowPlayingViewModel, NowPlayingViewModel> (new ContainerControlledLifetimeManager()); MainWindow window = container.Resolve<MainWindow>(); window.SelectedDirectoryView.DataContext = container.Resolve<ISelectedDirectoryViewModel>(); window.MediaListView.DataContext = container.Resolve<IMediaListViewModel>(); window.NowPlayingView.DataContext = container.Resolve<INowPlayingViewModel>(); window.Show(); } }
MVVM - Comments
Testability UI Logic and state is independent of UI layout. The layers have been successfully decoupled to assist in independent testing and development of components. The code is potentially simpler to extend into a larger application and will be simpler to maintain. High Concept Count, especially for a simple app.
Summary
The MVVM pattern is well suited for WPF / Silverlight development. Adopting MVVM can improve maintainability. Adopting MVVM can improve quality. Adopting MVVM frees up designer creativity. Adopting MVVM can improve the product.
Questions