Using the Model-View-View Model Pattern in WPF and UWP
Introduction
The Model-View-ViewModel (MVVM) pattern is a design pattern used to separate the user interface logic from the business logic in applications. It is widely used in WPF (Windows Presentation Foundation) and UWP (Universal Windows Platform) applications to create a clean separation of concerns, making the code easier to manage and test.
Model
The Model represents the data and the business logic of the application. It is responsible for retrieving and manipulating data, and it does not have any knowledge of the user interface.
Example Model
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
View
The View represents the user interface of the application. It defines the structure, layout, and appearance of what the user sees on the screen. The View binds to properties and commands in the ViewModel.
Example View (XAML)
<Window x:Class="MVVMDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="400">
<Grid>
<StackPanel>
<TextBox Text="{Binding Name}" />
<TextBox Text="{Binding Age}" />
<Button Command="{Binding SaveCommand}" Content="Save" />
</StackPanel>
</Grid>
</Window>
ViewModel
The ViewModel acts as an intermediary between the View and the Model. It handles the interaction logic and binds data from the Model to the View. The ViewModel exposes data and commands that the View can bind to.
Example ViewModel
public class PersonViewModel : INotifyPropertyChanged
{
private Person _person;
public string Name
{
get { return _person.Name; }
set
{
if (_person.Name != value)
{
_person.Name = value;
OnPropertyChanged("Name");
}
}
}
public int Age
{
get { return _person.Age; }
set
{
if (_person.Age != value)
{
_person.Age = value;
OnPropertyChanged("Age");
}
}
}
public ICommand SaveCommand { get; }
public PersonViewModel()
{
_person = new Person();
SaveCommand = new RelayCommand(Save);
}
private void Save()
{
// Save logic here
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
Data Binding
Data binding connects the View and the ViewModel. It allows the View to display and update data from the ViewModel.
Example Data Binding
<Window.DataContext>
<local:PersonViewModel />
</Window.DataContext>
Commands
Commands in MVVM are used to handle user interactions. They decouple the user interface from the logic that processes the interaction.
Example Command Implementation
public class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool> _canExecute;
public RelayCommand(Action execute, Func<bool> canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null || _canExecute();
}
public void Execute(object parameter)
{
_execute();
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}