Top Banner
MVVM Overview Frank Shoemaker MindCrafted Systems [email protected]
43
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

MVVM OverviewFrank ShoemakerMindCrafted Systems

[email protected]

Page 2: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Some background Some examples

Overview of MVVM

Page 3: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

MVVM stands for

Model

View

View-Model

MVVM

Page 4: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Simple Case

Page 5: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Typical class that covers a database Could be a WCF Service and its client

reference

Model

Page 6: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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)

ViewModel

Page 7: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Knows nothing about the View Does not “push” data into the view

TextBox1.Text = object.Name()

ViewModel

Page 8: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

View

Page 9: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

More on the ViewModel in MVVM

Page 10: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Existing StuffDatabase Tables Department

DepartmentID int

Name nvarchar(30)

StatusID int

CreateDate datetime

CreatedBy varchar(255)

LastChangedDate datetime

LastChangedBy varchar(255)

Column Name Data Type Allow Nulls

MCStatusMCStatusID

Name

DisplayOrder

Active

StatusID

CreateDate

CreatedBy

LastChangedDate

LastChangedBy

ItemItemId

Name

DepartmentID

PreferredSupplierID

SpecialOrder

UnitsInStock

ReorderLevel

LastOrderDate

AveragePrice

StatusID

CreateDate

CreatedBy

LastChangedDate

LastChangedBy

Page 11: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Existing StuffLibrary Class

Page 12: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

WPF

Page 13: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Business data Properties

Properties to return “Select” lists (AllSelect and StatusSelect)

The usual CRUD routines

Model Class

Page 14: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Encapsulates how it communications with the back-end

Uses Events to signal I/O successfully completed or an error occurred

In WPF it’s synchronous, but can be used as if it’s a asynchronous.

In Silverlight it’s async.

Model Class

Page 15: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

Model Class – I/OWPF - Synchronous

Page 16: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

Model Class – I/OSilverlight - Asynch

Page 17: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Private Sub Read_Completed(ByVal sender As System.Object, ByVal e As

ServiceReference1.FetchCompletedEventArgs) Handles myService.FetchCompleted

If IsNothing(e.Error) Then myData = e.Result RaiseEvent IOSuccessful("Read", New EventArgs()) Else RaiseEvent IOErrorOccurred("Read", e.Error) End If

End Sub

Model Class – I/OSilverlight - Asynch

Page 18: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Properties come in two flavorsData Properties

Name, StatusID, CreateDate, AllSelect

Form State properties IsEditing, IsNotEditing,

IsOKToBeginEdit

ViewModel Properties

Page 19: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Methods come in two flavorsCRUD Methods

Create, Read, Update, Delete

Implements the IEditableObject interface

BeginEdit, CancelEdit, EndEdit

ViewModel Methods

Page 20: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

ViewModel Class Events

Page 21: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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.

ViewModel Class Properties

Page 22: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

DataContext

Binding

Gluing the Pieces Together

Page 23: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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.

Setup the DataContext

Page 24: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

Set up the DataContext

Page 25: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Public Event PropertyChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs) _ Implements INotifyPropertyChanged.PropertyChanged

Data Binding - ViewModelINotifyPropertyChanged

Page 26: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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 SetEnd Property

Data Binding - ViewModelDeparment.CreatedBy

Page 27: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBox Text="{Binding Path=CreateDate, Mode=OneWay}" . . .

Path is within the DataContextMode=OneWay means the control won’t update the ViewModelSince it’s bound to CreateDate, when the PropertyChanged event is raised the control reloads from the CreateDate property in the ViewModelControls don’t need to be named

Data Binding - ViewDeparment.CreatedBy

Page 28: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBox Text="{Binding Path=Name,Mode=TwoWay, IsEnabled="{Binding

Path=IsEditing}" . . .

Binding to interpret the ViewModel’s state to the user.

Binding For State

Page 29: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<Button Name="Edit" Content="Edit" IsEnabled="{Binding Path=IsOKToBeginEdit}" Click="Edit_Begin" . . .

<Button Name="Save" Content="Save" IsEnabled="{Binding Path=IsEditing}" Click="Edit_Save" . . .

<Button Name="Cancel" Content="Cancel" IsEnabled="{Binding Path=IsEditing}" Click="Edit_Cancel" . . .

Binding for State

Page 30: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBox Text="{Binding Path=Name,Mode=TwoWay, . . .

Bi-directional binding.

TwoWay Data Bindning

Page 31: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBox Text="{Binding Path=Name,Mode=TwoWay, ValidatesOnExceptions=True}". . .

When the ViewModel throws the exception, the View changes

Validating in the ViewModel

Page 32: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<Style x:Key="styleTextBox" TargetType="TextBox"> . . . <Setter Property="Validation.ErrorTemplate" Value="{StaticResource errorEyeCatcher}"/> <Style.Triggers> <Trigger Property="Validation.HasError" Value="true"> <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> </Trigger> </Style.Triggers></Style>

Setting up Styles for Validation Binding

Page 33: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<!--Display a Red * next to the control with an error --><ControlTemplate x:Key="errorEyeCatcher"> <DockPanel> <Border BorderBrush="Red" BorderThickness="1" Padding="2"> <AdornedElementPlaceholder/> </Border> <TextBlock Foreground="Red" FontSize="24" Text="*"/> </DockPanel></ControlTemplate>

Setting up Styles for Validation Binding

Page 34: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBox Text="{Binding Path=Name,Mode=TwoWay, UpdateSourceTrigger=LostFocus, ValidatesOnExceptions=True}"IsEnabled="{Binding Path=IsEditing}"

. . .

When to Validate?

Page 35: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<ComboBox ItemsSource="{Binding Path=StatusSelect}"

DisplayMemberPath="Value" SelectedValuePath="Key" SelectedValue="{Binding

Path=StatusID, Mode=TwoWay}"

. . .

ComboBox Binding

Page 36: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

The state of Editing is maintained by the ViewModel

ViewModel exposes properties to indicate state

View interprets the ViewModel’s state to the user

Data BindingViewModel.FormStateMessage

Page 37: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBlock Text="{Binding Path=FormStateMessage}" . . .

Displaying the Status Message

Page 38: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<TextBlock Text="{Binding Path=FormStateMessage}" Foreground="{Binding Path=FormStateMessageType, Converter={StaticResource MessageForegroundColor}, ConverterParameter=FormStateMessageType}"

. . .

Use a converter routine to transform integer from the ViewModel into a color on theTextBox

Binding to Change Color of the Message if it’s an Error

Page 39: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

Converter Routine

Page 40: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

<Page.Resources> <converter:MessageForegroundColor x:Key="MessageForegroundColor" /></Page.Resources>

Setup the Converter Routine as a Resource in the XAML

Page 41: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

Since ViewModels know nothing about the UI, they can be driven with a programmatic test case.

Testing

Page 42: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

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

MVVM Wrap up

Page 43: MVVM Overview Frank Shoemaker MindCrafted Systems frank@mindcrafted.com.

View can be worked on by designers without messing up the ViewModel

Would benefit from a root ViewModel class for the state management.

MVVM Wrap up