Swiftorial Logo
Home
Swift Lessons
Tutorials
Learn More
Career
Resources

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; }
    }
}