Introduction
The MVVM is a design pattern based on the MVC/MVP patterns which are both trying to solve a similar problem. The MVVM pattern aims to separate the tightly bound UI code consisting of rendering, control actions and data-binding code.
For the sake of learning, I've kept the code very simple. I've attached the code as progressive but complete bundles so you can choose how much you want to learn at a time.
Background
The MVVM pattern can initially be quite intimidating to someone like me who has spent the last eight years familiarizing myself with the page behind code model. But I quickly discovered that it need not be this way and by adapting to this shift in the code paradigm, we can really benefit in many ways. I'd like to give Prabhjot Bakshi due credit for his wonderful article on the same subject, Brian Pring who introduced me to Silverlight with his exciting demos and Stephen Olah who actively contributed to my learning experience. I hope my experience in learning this pattern can benefit someone else.
The MVVM Concept
The MVVM pattern consists of 3 parts:
- View
- ViewModel
- Model
The view is bound to the viewmodel and any change in the model will automatically be reflected in the view. The ViewModel will handle any changes to the model and receive the events triggered on the view. Yes it’s that simple!
Part 1
Here, I would like to introduce the basic concepts of the MVVM pattern which help logically separate your UI code into the View, ViewModel and the Model.
View
The View consists of code that renders the Silverlight application UI, which would consist of your XAML code. Ideally in implementing the MVVM pattern in its true sense, we want to avoid any code behind. So what this means is we need to connect the View to the ViewModel in the XAML itself. You’ll need to pay extra attention to details in this section as this can save you many hours of debugging.
First, I register the ViewModel
namespace in my UserControl
attribute list.
xmlns : local ="clr-namespace:MVVMApp.ViewModel"
In my view, I have an outer Grid
which I connect to my ViewModel
:
<grid.datacontext>
<local:contactviewmodel>
</local:contactviewmodel></grid.datacontext>
Then an inner Grid
that I bind to an instance of my model:
<Grid DataContext="{Binding Path=mycontact}">
And finally the binding of the properties to the actual control that renders my text/data.
<textbox grid.row="0" text="{Binding Path=FirstName }">
<textbox grid.row="1" text="{Binding Path=SecondName }">
</textbox></textbox>
ViewModel
This is the tricky part, think of the ViewModel
as a specialized proxy that connects to the model and in terms of ASP.NET, think of this as your code behind where you would have handled event code and data-binding.
public class ContactViewModel
{
public Contact mycontact { get; set; }
public ContactViewModel()
{
Contact cont = new Contact();
cont.FirstName = "Ritesh";
cont.SecondName = "Ramesh";
mycontact = cont;
}
}
Model
Think of the model as the structure that will contain your data. The Model will not implement any functionality of any sorts. But in order to use the model in the MVVM pattern, we require the model to implement the INotifyPropertyChanged
interface. The INotifyPropertyChanged
interface is used to notify clients, typically binding clients that a property value has changed.
My model has two properties FirstName
and SecondName
and implements the INotifyPropertyChanged
interface. The NotifyPropertyChanged
method checks if the property is valid and notifies my view of the propertychange.
public class Contact : INotifyPropertyChanged
{
private string _FirstName;
public string FirstName {
get { return _FirstName; }
set { _FirstName = value;
NotifyPropertyChanged("FirstName");
}
}
private string _SecondName;
public string SecondName {
get { return _SecondName; }
set { _SecondName = value;
NotifyPropertyChanged("SecondName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
Part 2
Here, I would like to advance to the next stage of the MVVM pattern. That is implementing a command using a button control that will trigger the automated data binding of the View
and Model
within the ViewModel
.
View
I have added the following button syntax to the existing XAML of the View
.
<Button Grid.Row="2" Command="{Binding Path=DataContext.GetContact ,
ElementName= LayoutRoot }" Content="View"
CommandParameter="{Binding Path=Phone}" />
ViewModel
This is where most of the changes have been implemented to handle the buttons execution.
In my ViewModel
, I have introduced a GenericCommand
class that implements the ICommand
interface that exposes the CanExecute
, Execute
methods and an event CanExecuteChanged
.
CanExecute
- Here you can implement any verification code that needs to be checked before execution can be called. In my code, I have set it to always return true
.
Execute
- This is where you would implement any code that needs to be executed on the button click event.
CanExecuteChanged
- Fires when changes occur that affect whether or not the command should execute.
public class GenricCommand : ICommand
{
ContactViewModel _vm;
public GenricCommand( ContactViewModel vm)
{
_vm = vm;
}
public bool CanExecute(object parameter)
{
return true ;
}
public event EventHandler
CanExecuteChanged;
public void Execute( object
parameter)
{
_vm.showContact( );
}
}
Further, I have modified my ViewModel
class to include a method called GetContact
that returns an object of my GenricCommand
class.
public ICommand GetContact
{
get { return new GenricCommand(this); }
}
This in turn delegates the code to be executed when the button click is performed back to the showContact
method which is contained in my ViewModel
:
public void showContact()
{
mycontact.FirstName = "Ritesh";
mycontact.SecondName = "Ramesh";
}
Model
My model doesn’t require any changes.
Points of Interest
- This is but one implementation of the MVVM pattern, there are many other ways to accomplish the same thing.
- What the
ViewModel
should really consist of is still very much debatable, as an example, do I implement the sorting of a datagrid
in the View
itself or do I need to implement the functionality in the ViewModel
is still a mystery to me?
References