370 likes | 664 Views
MVVM in the Real World. or How I Learned to Stop Worrying and Love the Binding Bryan Anderson. About Me. Consultant for ILM Worked with WPF & Silverlight for the past 2 years In industry for 4 ½ years Programming for 14 years
E N D
MVVM in the Real World or How I Learned to Stop Worrying and Love the Binding Bryan Anderson
About Me • Consultant for ILM • Worked with WPF & Silverlight for the past 2 years • In industry for 4 ½ years • Programming for 14 years • Of all of the features to come to .NET 4.0, Code Contracts are the most important
What am I going to talk about? • Vocabulary & relevant Design Patterns • Presentation Model pattern • MVVM Architecture • Compare MVVM to MVC • Religious fights you’ll encounter when implementing MVVM • Common issues you’ll run into with MVVM and their solutions
INotifyPropertyChanged //Notifies clients that a property value has changed. publicinterfaceINotifyPropertyChanged { //Occurs when a property value changes. eventPropertyChangedEventHandler PropertyChanged; }
INotifyCollectionChanged //Notifies listeners of dynamic changes, such as when items get //added and removedor the whole list is refreshed. publicinterfaceINotifyCollectionChanged { //Occurs when the collection changes. eventNotifyCollectionChangedEventHandler CollectionChanged; } //Describes the action that caused a CollectionChangedevent. publicenumNotifyCollectionChangedAction { Add, Remove, Replace, Move, Reset }
Data Binding • Keeps data in two properties “bound” together • Allows data to flow in either or both directions • Uses PropertyChanged & CollectionChanged to keep values updated
Value Converter • Implements IValueConverter or IMultiValueConverter • object Convert(object value, Type targetType, object parameter, CultureInfo culture) • object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) • Converts inputs from one value to another and back • Used extensively in data binding
Dependency Property • Looks like a standard CLR property on the class’s interface • Adds additional infrastructure features like • Data Binding • Change Notification • Value Coercion • Used extensively by WPF and Silverlight to create fast, reactive user interfaces
User Control • Groups a related set of controls • Reduces repetition – DRYer • Has its own code behind – allows new dependency properties
Commands • An implementation of the Command Pattern • In WPF & Silverlight the ICommand interface is used to define a class that represents a command • bool CanExecute(object parameter) • void Execute(object parameter) • event EventHandler CanExecuteChanged • Frequently implemented by creating a DelegateCommand class
Design patterns Design patterns give programmers a proven solution to a given problem with known benefits, drawbacks, and a shared vocabulary. • Command – Encapsulates method calls • Mediator - Encapsulates messages between objects • Adapter – Translates one interface into another • Façade – Simplifies a larger interface • Singleton - Restricts a class to a single instance • Factory – Encapsulates the creation of an object • Etc.
Not this kind of Factory http://xkcd.com/387/
The Purpose of Architecture Patterns Architectural patterns serve the same purpose as other design patterns, but they focus on the whole application or a very large portion of it.
The Purpose of Architecture Patterns • Guide the separation of concerns • Encapsulate what changes • UI • Web services • Databases • Anything else that interfaces with something outside the application
Goals of the Presentation Model • Separate presentation from functionality • Testability • Consistency • Maintainability • Allow a combined Blend/Visual Studio workflow
Presentation Model • Abstract Pattern that defines a family of platform/framework specific patterns • MVVM – WPF, Silverlight • MVC – Web • MVP – Winforms • Designed to pull the state and behavior out of the View into a more stable and testable layer View Presentation Model Model
Presentation Model • Abstract Pattern that defines a family of platform/framework specific patterns • MVVM – WPF, Silverlight • MVC – Web • MVP – Winforms • Designed to pull the state and behavior out of the View into a more stable and testable layer View Presentation Model Model
MVVM Architecture – Model • Responsible for business logic • Interacts with persistent storage, e.g. database, web services, files, etc. • Capable of being shared among related applications Unit Tests View View Model Model File System Database Web Services
MVVM Architecture – View Model • Should be thought of as an Abstract View • Exposes properties and commands for use in a View • Gets data from the Model and updates it according to property changes and command calls Unit Tests View View Model Model File System Database Web Services
MVVM Architecture - View • Presents data to the user • Handles input • Interacts with the View Model by data binding to properties and commands • Should contain no logic that isn’t entirely a view concern, e.g. which screen to show Unit Tests View View Model Model File System Database Web Services
MVVM Architecture - Tests • Acts as another View • Interacts with the Model and View Model to ensure correct behavior • Provide an early warning that the architecture isn’t correct • If testing is difficult, coupling is too high or concerns aren’t separated Unit Tests View View Model Model File System Database Web Services
MVC • The Model holds data and handles business logic • The Controller receives input and makes changes to the View and Model accordingly • The View renders the Model into a form suitable for interaction Controller View Model
Religious Fights • Multiple, mutually exclusive options • People form strong opinions and will argue the benefits of their choice for all eternity • Each side has its own benefits and drawbacks • A decision needs to be made before the “correct choice” can be determined • In the end it comes down to a combination of reason and instinct
Religious Fights – Round 1 View Model Driven • Allows more complete testing of logic to open new Views/View Models • Tends to be DRYer as applications grow • More difficult to use in Silverlight projects View Driven • Easy to track which View Model is used by a View • Much easier to use when sharing code between WPF and Silverlight • Difficult or confusing for a single View to be used with multiple View Models
Religious Fights – Round 2 How much code should I actually have in the View’s code behind? • Value converters are fine as long as they’re only converting values • User Control code behind should only contain Dependency Property definitions and rare view-specific event handlers • DataTemplateSelectors as long as their code is limited to choosing between DataTemplates • Otherwise there should be no code-behind
Religious Fights – Round 3 Should the View be allowed to use/display a Model class directly or should all interactions be through the View Model? • The View should never edit a Model instance • My rule of thumb – Only allow the view to display immutable Model objects, even then try to avoid it • It should be considered technical debt if done, but it’s a relatively harmless area to take on debt
Religious Fights – Round 4 Where should INotifyPropertyChanged and INotifyCollectionChanged be used? • Definitely in the View Model • Occasionally in the View - usually in Custom Controls and more rarely User Controls • It’s becoming more accepted to them in the Model unless added to push updates to a View
Common Issues & Solutions • Notifying users from a View Model, i.e. How do I show a message box? • How do I handle non-command events without code behind? • Something should or should not be shown based on state. What goes in the View vs. View Model? • Should I use an additional property or the command parameter to pass contextual data to a View Model’s command? • View Models seem to copy all of my Model’s properties
Notifying users from a View Model • Message boxes are annoying
Notifying users from a View Model • Message boxes are annoying • Messages to the user are useful • Use a mediator – Allows you to aggregate messages from all of your VMs, log them, and display them. Also easy to test. • If you only need it in one or two places an Error/Notification property or, more rarely, event works well. • Implement the IDataErrorInfo interface for notifications related to property validation
Handling events without code behind • Usually done using an attached behavior, search for “Attached Command Behavior” • Can it be handled by binding? • If absolutely necessary and there’s no logic involved it can be put into code behind.
Code Behind & Gotos http://xkcd.com/292 Beware of Raptor Attacks
Visibility based on state, what goes in the View vs. View Model? • Is it a View-only concern? E.g. Master/Detail view • Bind the detail view to the selected master item • Is it a View Model concern? E.g. IsEditMode • Use a DataTemplateSelector if available to switch Views • Use Triggers, Visual State Manager, or another method to switch views based on the View Model properties • Is it a combination? E.g. IsBusy • Use the Visual State Manager if available
Property or command parameter? • Would the property be referenced anywhere outside of the command(s)? • Does the property make sense in the context of the View Model’s interface? • Is the command used in multiple places that would need to set the property to different objects?
View Models just copy my Models • View Models are not just Façades or Adapters for Model classes • View Models are not the code behind for a View • View Models are an Abstract View or the Model for a View • View Models will present multiple Models and multiple View Models might use the same Model
Questions? I love feedback! Bryan Anderson bryan.anderson@ilmservice.com