Freigeben über


"Advanced MVVM" by Josh Smith

davihard's "Cliffs Notes" of "Advanced MVVM"

WPF Review/MVVM Intro

XAML based layout flow and user interaction event definition; they do some nice painting and rendering performance for you.

"It was once commonly said that all roads lead to Rome. Today all WPF and Silverlight best practices lead to the Model-View-ViewModel design pattern."

This is great because it alludes to the fact that it's not just Silverlight that does all this XAML sugary goodness, it was WPF first, and now Silverlight. When asked if Silverlight is the death of WPF, most Silverlight evangelists chime in with, "(paraphrase:) Silverlight's the best thing to happen to WPF; Silverlight doesn't kill WPF, it brings a technology that's been in the industry now for a few years back under a fresh spotlight."

"The fundamental mechanisms involved in creating applications based on MVVM are data binding and commands. ViewModel objects expose properties to which Views are bound, including properties that return command objects. When the properties of a ViewModel change, the Views bound to that ViewModel receive a notification when the ViewModel raises its PropertyChanged event (which is the sole member of the INotifyPropertyChanged interface). The data binding system will automatically get the new value from the modified property and update the bound properties in the View. Similarly, changes made to the data in the View are pushed back to the ViewModel via bindings. When the user clicks on a button whose Command property is bound to a command exposed by a ViewModel, that command executes and allows the ViewModel to act on the user's interaction. If the ViewModel needs to expose a modifiable collection of objects to a View, the ViewModel can use ObservableCollection<T> to get collection change notifications for free (which the binding system knows how to work with). It's all very simple to implement because data bindings do the grunt work of moving bound data values around when necessary.

The magic glue that ties Views and ViewModels together is, more often than not, the DataContext property inherited by all visual elements. When a View is created, its DataContext can be set to a ViewModel so that all elements in the View can easily bind to it. This is not a hard and fast rule, though. Some people prefer to put their ViewModels into resource dictionaries and bind to them via resource references. That technique can make it easier to work with Views in Microsoft's Expression Blend visual design tool."

Best practices for designing Views

"Advanced MVVM" mentions the Mole visualizer which is nice for inspecting the "visual tree" of a piece of UI.

"In non-trivial user interfaces there are various bits of code required to make a View work properly. If that code relies on UI elements, resources, or anything else belonging to the realm of the user interface, I see no reason not to put that code into the View's code-behind."

Best practices for designing ViewModels

Each View class should have a corresponding ViewModel class; the View's DataContext is set to its ViewModel object. Views should reference ViewModels from a separate project/assembly. The MVVM Foundation library on CodePlex "contains several useful classes for developers writing ViewModels. The MVVM Foundation classes used in this application are ObservableObject and RelayCommand."

Rather creating and assigning the ViewModel in the View code-behind, XAML can also handle declaration and assignment for the DataContext/ViewModel.

    1:  <UserControl.DataContext>    
    2:      <viewModels:FooViewModel/>
    3:  </UserControl.DataContext>
  

"WPF requires collection change notifications to occur on the UI thread."

"DataTriggers in the View layer bind to that property in order to turn on/off visual effects for the bubble group under the cursor. You can see how that works by looking at the Style whose x:Key is 'BubbleGridStyle' in the BubbleViewResources.xaml file, if you re interested."

Deciding on what state and logic belongs in Views versus ViewModels

"[L]imiting your Views to only the code that is specific to their events, elements, resources, etc. enables you to keep the various application layers clear, logical, and loosely coupled. Separation of concerns is a worthwhile goal when writing software."

Coordinating animated transitions and unlimited undo between the ViewModel and View

"When pending tasks are made available, three methods work together to process them and perform animated transitions. These methods are in the code-behind of [the View]"

The Unit of Work pattern is an elegant solution for animation precipitating input timing issues; this task-based architecture lends itself well to animated transitions between tasks and ease of unlimited undo functionality.