Tuesday, June 8, 2010

MVVM For Beginners

I have just started my work using MVVM ( Model-View-View Model ) pattern and many of you may know about this pattern as well.The powerful data-binding support in WPF framework provides the basis for MVVM pattern. In this post I will show you simple example to display data in the view part using the view model. Here is explanation of Model, view and ViewModel.

Model


The Model is defined as in MVC; it is the data or business logic, completely UI independent, that stores the state and does the processing of the problem domain. The Model is written in code or is represented by pure data encoded in relational tables or XML.

View

A View is defined in XAML and should not have any logic in the code-behind. It binds to the view-model by only using data binding.In simple examples, the View is data bound directly to the Model. Parts of the Model are simply displayed in the view by one-way data binding. Other parts of the model can be edited by directly binding controls two-way to the data.

ViewModel


The term means “Model of a View”, and can be thought of as abstraction of the view, but it also provides a specialization of the Model that the View can use for data-binding. In this latter role the ViewModel contains data-transformers that convert Model types into View types, and it contains Commands the View can use to interact with the Model.
The ViewModel exposes public properties, commands, and abstractions. The ViewModel has been likened to a conceptual state of the data as opposed to the real state of the data in the Model.

Let us start with our example of the MVVM which is simple one. I have created three folder in my project with names Model, view and viewModel so that I have Placed my model class in the model folder and View in the view folder and viewModel class in the viewModel folder. As I have added class in the respective folder the namespace is append with view, model and viewModel.In the model folder I have on one class with the name of customer which define the properties of the customer like user ID, first name, last name, email ID, contact number and date of birth. The customer class is inherit from the INotifyPropertyChanged interface which is used to notify whenever there is any changed in the property value which I will show you later. In the View Model folder I have one class names CustomerViewModel which contains property for the customer class in the model folder and also a viewTitle property.
View:
Let us start to design the view of the application. Below is the xaml of the view I have created for the example code.
<Window.DataContext >
<local:CustomerViewModal> </local:CustomerViewModal>
</Window.DataContext>
<GroupBox Header="{Binding Path=ViewTitle}">
<Grid DataContext="{Binding Path=Customers}">
<Grid.RowDefinitions >
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="25*"/>
<ColumnDefinition Width="75*"/>
</Grid.ColumnDefinitions>

<TextBlock Text="User ID :" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<TextBox Grid.Row="1" Grid.Column="1" Margin="2,3,2,3" Text="{Binding Path=UserID, Mode=TwoWay}"> </TextBox>

<TextBlock Text="Frist Name :" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<TextBox Grid.Row="2" Grid.Column="1" Margin="2,3,2,3" Text="{Binding Path=FirstName, Mode=TwoWay}"> </TextBox>

<TextBlock Text="Last Name :" Grid.Row="3" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<TextBox Grid.Row="3" Grid.Column="1" Margin="2,3,2,3" Text="{Binding Path=LastName,Mode=TwoWay}"> </TextBox>

<TextBlock Text="Email Address :" Grid.Row="4" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<TextBox Grid.Row="4" Grid.Column="1" Margin="2,3,2,3" Text="{Binding Path=EmailID,Mode=TwoWay}"> </TextBox>

<TextBlock Text="Contact No. :" Grid.Row="5" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<TextBox Grid.Row="5" Grid.Column="1" Margin="2,3,2,3" Text="{Binding Path=ContactNumber, Mode=TwoWay}"> </TextBox>

<TextBlock Text="Date Of Birth :" Grid.Row="6" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0"> </TextBlock>
<my:DatePicker Grid.Column="1" Grid.Row="6" Margin="2,3,2,3" Text="{Binding Path=DateOfBirth, Mode=TwoWay}" />

<Button Content="Save" Grid.Row="7" Grid.Column="1" Width="75" Margin="0,3,80,3" HorizontalAlignment="Right"> </Button>
<Button Content="Close" Grid.Row="7" Grid.Column="1" Width="75" Margin="0,3,-1,3" HorizontalAlignment="Right" > </Button>

</Grid>
</GroupBox>


And here is the output of the design.Here I have used the used two controls one is the textBox and the second one is the DatePicker control and two buttons controls which are not working in this example. I will try to discuss the working of the buttons in the MVVM pattern.

Now Let us discuss the view in depth.If you see the xaml for each of the textBox then you will see that I have bind each of the textbox text property, and I have used the two way binding mode which mean to notify the any change in the value of the property from the view to the view model or model. If you don't have any idea about the binding then here is some detail about the binding mode.The Mode (which is of type BindingMode) is an enumeration with three possible values as

OneTime:
Binding sets the target and then the binding is completed. This is great for displaying data that rarely or never changes
OneWay:
Binding sets the target and keeps it up to date as the source changes. This is great for displaying data that the user is not permitted to change.
TwoWay:
Binding sets the target and keeps the target up to date as the source changes and keeps the source up to date as the user changes the target or changes something else in the application that will cause your application to change the source.

As I have set the binding mode to twoWay so if any change in the the value of the property is done in the view will be send back to the data source as well.


ViewModel
In the viewmodel I have class with only two properties one for the ViewTitle and the second one is the Customers which is of type Customer the class defined in the model. And I have Initialize the both the properties in the constructor of the viewModel class. I have also bind the Customers class to the grid which hold the textBox and the date picker control so that the Properties of the Customer can be bind to the text properties of the textBox.

Model:
In the Model class I have only defined the properties of the Customer which is inherits from the INotifyPropertyChanged interface.This interface requires only one thing: that the class have an event of type PropertyChangedEventHandler (named PropertyChanged by convention), Implicit in supporting binding, however, is that your business object must, by convention, fire the PropertyChanged event when any property that is tied to a UI control is changed (and the most common way to change it, is to set its value). I have also raise the RaisePropertyChanged event for the first name and last name. whenever values of these two properties changes in the view they will be notify in the model as well.

You can download the source code from here
All and any comments / bugs / suggestions are welcomed!


5 comments:

Anonymous said...

Hello Asim
Thats good

Gul

Anonymous said...

hello Asim,

its a very good, crisp and clear article.

Thanks,
GM.

Asim Sajjad said...

@Anonymous: thanks for your comments and time to read the article

Rich said...

Nice intro to MVVM, even I could understand it!
By changing the email textbox binding to LastName and putting a breakpoint in the customer class at RaisePropertyChanged("LastName"); it is possibly to see the event update the email textbox with the new LastName.

Anonymous said...

Article is good. visual studio 2010 do not have Silver light with MVVM template. Silver light with MVVM structure, developer manually segregate the folder ?