Design Patterns

MVVM Part 2: The Command Spellbook

Estimated reading: 4 minutes 72 views Contributors

Up to now, the heroes simply appear in a scroll-like slideshow. Let’s add the ability to summon them one by one, like turning pages in a storybook. This introduces commands, one of the central spells of MVVM.


Act 8: The Power of Commands

Think of a Command as a “button spell.”
In the old world (non-MVVM apps), buttons call methods directly from the code-behind, creating messy entanglements.
In the MVVM world, buttons are bound to commands in the ViewModel — so the logic and interface remain cleanly separated.


Act 9: Preparing the Command Spell

Create a folder named Commands, and add a class called RelayCommand.cs.

using System;
using System.Windows.Input;

namespace RPGMVVMApp.Commands
{
    public class RelayCommand : ICommand
    {
        private readonly Action<object> execute;
        private readonly Func<object, bool> canExecute;

        public event EventHandler CanExecuteChanged;

        public RelayCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            this.execute = execute;
            this.canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return canExecute == null || canExecute(parameter);
        }

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

        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged?.Invoke(this, EventArgs.Empty);
        }
    }
}

This RelayCommand is our universal command pattern — like a reusable spell formula that any button can cast.


Act 10: Upgrading the Wizard (ViewModel)

Open HeroViewModel.cs and add logic for “Next Hero.”

using System.Collections.ObjectModel;
using RPGMVVMApp.Models;
using RPGMVVMApp.Commands;
using System.ComponentModel;

namespace RPGMVVMApp.ViewModels
{
    public class HeroViewModel : INotifyPropertyChanged
    {
        private int currentHeroIndex;
        private Hero currentHero;

        public ObservableCollection<Hero> Heroes { get; set; }
        public Hero CurrentHero
        {
            get => currentHero;
            set
            {
                currentHero = value;
                OnPropertyChanged(nameof(CurrentHero));
            }
        }

        public RelayCommand NextHeroCommand { get; set; }

        public HeroViewModel()
        {
            Heroes = new ObservableCollection<Hero>
            {
                new Hero { Name="Aeris the Brave", ImagePath="Images/hero1.png", Quote="Courage is the quiet voice that says 'try again'." },
                new Hero { Name="Luna of the Vale", ImagePath="Images/hero2.png", Quote="The stars whisper to those who listen." },
                new Hero { Name="Korran the Flame", ImagePath="Images/hero3.png", Quote="Fire tests all things." }
            };

            CurrentHero = Heroes[0];
            currentHeroIndex = 0;

            NextHeroCommand = new RelayCommand(o => NextHero());
        }

        private void NextHero()
        {
            currentHeroIndex = (currentHeroIndex + 1) % Heroes.Count;
            CurrentHero = Heroes[currentHeroIndex];
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

You’ve now given the wizard (ViewModel) the ability to change heroes — one command, cleanly separated from the View.


Act 11: Enchanting the View

Edit MainWindow.xaml to show just one hero and add a button:

<Window x:Class="RPGMVVMApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Hero Showcase" Height="400" Width="600" Background="#1C1C1C">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <Image Source="{Binding CurrentHero.ImagePath}" Height="200" Margin="0,10"/>
            <TextBlock Text="{Binding CurrentHero.Name}" FontSize="24" Foreground="Gold" TextAlignment="Center"/>
            <TextBlock Text="{Binding CurrentHero.Quote}" FontSize="16" Foreground="LightGray" TextAlignment="Center" Margin="0,5,0,10"/>
            <Button Content="Next Hero"
                    Command="{Binding NextHeroCommand}"
                    Width="120"
                    Background="#444"
                    Foreground="White"
                    Padding="5"/>
        </StackPanel>
    </Grid>
</Window>

Now, every time learners click the Next Hero button, the ViewModel’s command runs and updates the displayed hero. No event handlers, no spaghetti — pure data binding magic.


Act 12: Reflection — The Design Pattern Revealed

What you’ve created isn’t just a slideshow. It’s a micro-architecture — a living example of separation of concerns.

RoleIn Our AppAnalogy
ModelHero classThe scroll of character stats
ViewMainWindow.xamlThe enchanted mirror where players see the hero
ViewModelHeroViewModel.csThe wizard interpreting commands and fetching data

This structure keeps apps clean and testable. It’s how large-scale software — from finance dashboards to video editors — stays organized.


Mini Challenge for Learners

Add a “Previous Hero” command or an “Add New Hero” feature.
Can they do it without touching the View’s code-behind? That’s the test of true MVVM mastery.


Share this Doc

MVVM Part 2: The Command Spellbook

Or copy link

CONTENTS

Chat Icon Close Icon