Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

MVVM - Demo

0.00/5 (No votes)
6 Aug 2012 2  
If you are new to MVVM this is the place to start. Explains MVVM through an example.

MVVM

The model-view-viewmodel is a typically WPF pattern. It consists of a view that gets all the user input and forwards it to the viewmodel, typically by using commands. The view actively pulls the data from the viewmodel by using data binding. The model doesn’t know about the ViewModel and the ViewModel doesn’t know about the View. 

Explaining MVVM through an example

Let’s create a sample Patient Management Application using MVVM. Going step by step we must first define our Model, then define the ViewModel and finally the View.

Step 1 - Creating the Model:

Def: The Model is often referred to as Domain Model, completely UI independent that stores the state and helps in the processing of the problem domain.

In our example Model becomes the DOM object which is nothing but the patient entity. The sample below shows the patient Entity.

public class Patient
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Int64 MobileNumber { get; set; }
}   

Step 2 – Creating the View Model

Def : 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 has been likened to a conceptual state of the data as opposed to the real state of the data in the Model. 

Coming back to our example lets create the PatientViewModel which will expose the Properties(which contains the Data) and Commands (User actions) which will be binded to the view. 

Public  Properties : 

All the data that needs to be binded to the View will be exposed as public properties. The View Model will implement PropertyChanged Event so that the view will be updated automatically whenever there is a change in the ViewModel. To do this we are triggering the PropertyChanged event when the property is set.

public class PatientDetailViewModel: INotifyPropertyChanged
{
//    ...
    public int Id
    {
        get { return domObject.Id; }
        set
        {
       domObject.Id = value;
       OnPropertyChanged("Id");
        }
    }
//    ...
    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
           PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
} 

Commands :
Def : The main idea is to move the whole presentation logic to the view model. This can be attained by using another feature of WPF, namely Commands. Commands can be bound like data and are supported by many elements as buttons, toggle buttons, menu items, checkboxes and input bindings. The goal here is not to have any line of logic in the code-behind of a view.

The View will execute commands on user action and the commands will be implemented in the ViewModel. To do this, you can’t use the standard WPF RoutedUIEvent, but you can easily develop your own command classes. A common way to do this is to create a command object that calls a delegate you specify.
Here is an example of how you can define a custom command class which you will later use when you are defining the commands in the ViewModel.

public class RelayCommand : ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;

    public RelayCommand(Action<object> execute)
        : this(execute, null){}

    public RelayCommand(Action<object> execute,
Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

Coming back to our example, our sample app requires Add, Delete & Search functionalities. The sample shows how to implement Add command using the RelayCommand that we defined above.

public class PatientDetailViewModel: INotifyPropertyChanged
{
    public ICommand AddPatientCmd { get { return _addPatientCmd; } }
    public PatientDetailViewModel()
    {
        _addPatientCmd = new RelayCommand(Add, CanAdd);
    }

    public bool CanAdd(object obj)     {  //Logic   }
    public void Add(object obj)  {  //Logic   }
} 

Step 3 – Creating the View

Def : 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. The view involves mostly just setting up the UI and bindings to the ViewModel. The DataContext property for this control will be set to the ViewModel.

As we have created the PatientViewModel all we need to do is create the PatientDetailView and then bind the ViewModel as the DataContext. The Sample here shows Property binding and Command binding.

<UserControl ...>
    <!--Bind the View Model to the View. -->
    <UserControl.DataContext>
       <ViewModels:PatientDetailViewModel/>
    </UserControl.DataContext>
    ....
    <TextBox Name="TbxName" .... 
         Text="{Binding Path=Name}"/>    
    ....
    <Button Name="BtnAdd" Content="Add" ....
        Command="{Binding AddPatientCmd}"/>   
.....             
</UserControl>

Points to Note 

Since in a real life project you usually have more than one data object per view, using a view model becomes convenient since you can aggregate all data objects into one single View Model that exposes the aggregated data as properties and that can be bound to the DataContext.

The key point to MVVM is to make the view completely concerned with how data looks, never about behavior. Ideally, a view should be completely plug-and-play, with the only work being to hook up the bindings to the ViewModel.

In addition, separating all the behavior from the GUI allows you to be far more complete in unit testing.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here