Title: MVVM Overview
1MVVM Overview
- Frank Shoemaker
- MindCrafted Systems
- frank_at_mindcrafted.com
2Overview of MVVM
- Some background
- Some examples
3MVVM
- MVVM stands for
- Model
- View
- View-Model
4Simple Case
5Model
- Typical class that covers a database
- Could be a WCF Service and its client reference
6ViewModel
- Provides data to and from the View
- Responds to both the View and the Model
- Informs the View of changes in the data
- Reusable (at least much more than code behind a
form)
7ViewModel
- Knows nothing about the View
- Does not push data into the view
- TextBox1.Text object.Name()
8View
- Uses Binding to subscribe to the ViewModel
- Interprets business data and state of ViewModel
to the human - Nothing but Presentation - XAML
- No or minimal code-behind
9More on the ViewModel in MVVM
- WPF/Silverlight data binding is what makes things
work - ViewModel presents a published interface to the
View - Binding in the XAML instead of code
- More use of Declarative Programming
10Architecture
11Existing StuffDatabase Tables
12Existing StuffLibrary Class
13WPF
14Model Class
- Business data Properties
- Properties to return Select lists (AllSelect
and StatusSelect) - The usual CRUD routines
15Model Class
- Encapsulates how it communications with the
back-end - Uses Events to signal I/O successfully completed
or an error occurred - In WPF its synchronous, but can be used as if
its a asynchronous. - In Silverlight its async.
16Model Class I/OWPF - Synchronous
- Public Sub Read(ByVal id As Integer)
- Try
- myLibraryObj.MCFetch(id)
- RaiseEvent IOSuccessful("Read", New
EventArgs()) - Catch ex As Exception
- RaiseEvent IOErrorOccurred("Read", ex)
- End Try
- End Sub
17Model Class I/OSilverlight - Asynch
- Public Sub Read(ByVal id As Integer)
- Try
- myService.FetchAsync(id,
ServiceReference1.myContextPayloadType.Heavy
) - Catch ex As Exception
- RaiseEvent IOErrorOccurred("Read", ex)
- End Try
- End Sub
18Model Class I/OSilverlight - Asynch
- Private Sub Read_Completed(ByVal sender As
System.Object, ByVal e As ServiceReference1.Fetc
hCompletedEventArgs) Handles myService.FetchCompl
eted - If IsNothing(e.Error) Then
- myData e.Result
- RaiseEvent IOSuccessful("Read", New
EventArgs()) - Else
- RaiseEvent IOErrorOccurred("Read",
e.Error) - End If
- End Sub
19ViewModel Properties
- Properties come in two flavors
- Data Properties
- Name, StatusID, CreateDate, AllSelect
- Form State properties
- IsEditing, IsNotEditing, IsOKToBeginEdit
20ViewModel Methods
- Methods come in two flavors
- CRUD Methods
- Create, Read, Update, Delete
- Implements the IEditableObject interface
- BeginEdit, CancelEdit, EndEdit
21ViewModel Class Events
- Implements INotifyPropertyChanged interface
- Notify the View that a property has changed its
value - Allows the View to respond to reflect the change,
if it wants to
22ViewModel Class Properties
- Present some properties in more than one way for
the convenience of the View - IsEditing
- True if the user is currently editing the
business object - IsNotEditing
- True if the user is NOT currently editing the
business object.
23Gluing the Pieces Together
24Setup the DataContext
- This example sets up the DataContext in code
- Create a new instance of the ViewModel
- Bind the View to the ViewModel Instance
- All Controls on the View then inherit the
DataContext from the page.
25Set up the DataContext
- Private Sub Page_Loaded(ByVal sender As Object,
ByVal e As
System.Windows.RoutedEventArgs) - myVM New ViewModel.DepartmentVM()
- ' Set the DataContext for the
- ' entire page to the ViewModel
- Me.DataContext myVM
- End Sub
26Data Binding - ViewModelINotifyPropertyChanged
- Public Event PropertyChanged(ByVal sender As
Object, - ByVal e As
PropertyChangedEventArgs) _ - Implements INotifyPropertyChanged.Property
Changed
27Data Binding - ViewModelDeparment.CreatedBy
- Public Property CreatedBy() As String
- Get
- Return myModel.CreatedBy
- End Get
- Set(ByVal value As String)
- myModel.CreatedBy value
- RaiseEvent PropertyChanged(Me, New
PropertyChangedEventArgs("CreatedBy")) - End Set
- End Property
28Data Binding - ViewDeparment.CreatedBy
- ltTextBox Text"Binding PathCreateDate,
ModeOneWay" . . . - Path is within the DataContext
- ModeOneWay means the control wont update the
ViewModel - Since its bound to CreateDate, when the
PropertyChanged event is raised the control
reloads from the CreateDate property in the
ViewModel - Controls dont need to be named
29Binding For State
- ltTextBox Text"Binding PathName, ModeTwoWay,
IsEnabled"Binding PathIsEditing" - . . .
- Binding to interpret the ViewModels state to
the user.
30Binding for State
- ltButton Name"Edit" Content"Edit"
- IsEnabled"Binding PathIsOKToBeginEdit"
- Click"Edit_Begin" . . .
- ltButton Name"Save" Content"Save"
- IsEnabled"Binding PathIsEditing"
- Click"Edit_Save" . . .
- ltButton Name"Cancel" Content"Cancel"
- IsEnabled"Binding PathIsEditing"
- Click"Edit_Cancel" . . .
31TwoWay Data Bindning
- ltTextBox Text"Binding PathName, ModeTwoWay,
. . . - Bi-directional binding.
32Validating in the ViewModel
- ltTextBox Text"Binding PathName, ModeTwoWay,
ValidatesOnExceptionsTrue" - . . .
- When the ViewModel throws the exception, the View
changes
33Setting up Styles for Validation Binding
- ltStyle xKey"styleTextBox" TargetType"TextBox"gt
- . . .
- ltSetter Property"Validation.ErrorTemplate"
- Value"StaticResource
errorEyeCatcher"/gt - ltStyle.Triggersgt
- ltTrigger Property"Validation.HasError"
Value"true"gt - ltSetter Property"ToolTip"
- Value"Binding RelativeSourceRelati
veSource Self, - Path(Validation.Errors)0.Er
rorContent"/gt - lt/Triggergt
- lt/Style.Triggersgt
- lt/Stylegt
34Setting up Styles for Validation Binding
- lt!--Display a Red next to the control with an
error --gt - ltControlTemplate xKey"errorEyeCatcher"gt
- ltDockPanelgt
- ltBorder BorderBrush"Red"
BorderThickness"1" Padding"2"gt - ltAdornedElementPlaceholder/gt
- lt/Bordergt
- ltTextBlock Foreground"Red" FontSize"24"
Text""/gt - lt/DockPanelgt
- lt/ControlTemplategt
35When to Validate?
- ltTextBox Text"Binding PathName, ModeTwoWay,
UpdateSourceTriggerLostFocus,
ValidatesOnExceptionsTrue" - IsEnabled"Binding PathIsEditing"
- . . .
36ComboBox Binding
- ltComboBox ItemsSource"Binding
PathStatusSelect" - DisplayMemberPath"Value"
- SelectedValuePath"Key"
- SelectedValue"Binding
PathStatusID, ModeTwoWay" - . . .
37Data BindingViewModel.FormStateMessage
- The state of Editing is maintained by the
ViewModel - ViewModel exposes properties to indicate state
- View interprets the ViewModels state to the user
38Displaying the Status Message
- ltTextBlock Text"Binding PathFormStateMessage"
- . . .
39Binding to Change Color of the Message if its an
Error
- ltTextBlock Text"Binding PathFormStateMessage"
- Foreground"Binding PathFormStateMessageType,
- ConverterStaticResource
MessageForegroundColor,
ConverterParameterFormStateM
essageType" - . . .
- Use a converter routine to transform integer from
the ViewModel into a color on theTextBox
40Converter Routine
- Public Function Convert(ByVal value As
Object, - ByVal targetType As System.Type,
- ByVal parameter As
Object, ByVal culture As System.Globalization
.CultureInfo) _ - As Object Implements
System.Windows.Data.IValueConverter.Convert - If CInt(value) 1 Then
- ' Informational message
- Return "Black"
- Else
- ' Error message
- Return "Red"
- End If
- End Function
41Setup the Converter Routine as a Resource in the
XAML
- ltPage.Resourcesgt
- ltconverterMessageForegroundColor
xKey"MessageForegroundColor" /gt - lt/Page.Resourcesgt
42Testing
- Since ViewModels know nothing about the UI, they
can be driven with a programmatic test case.
43MVVM Wrap up
- Loose coupling between the Model, ViewModel, and
View - Bright lines between areas of concerns
- At least some chance of reusability of the
ViewModel - ViewModel is independently testable
44MVVM Wrap up
- View can be worked on by designers without
messing up the ViewModel - Would benefit from a root ViewModel class for the
state management.