We’ll start with the EditCustomerPage. As a reminder – that’s how it looks:


First of all we need a view model class. Create a class named EditCustomerPageVM, and derive it from the class PageVM. Add a constructor with a parameter of type ISystemConnector and pass the parameter to the base class constructor:

namespace SimpleMVVM.ViewModels
{
    public class EditCustomerPageVM : PageVM
    {
        public EditCustomerPageVM(ISystemConnector systemConnector)
            : base(systemConnector)
        {
        }
    }
}

The page is actually displayed when the „Edit Customer Page“ button is clicked. That means that the MainMenuPageVM class must be able to switch to another page. Most pages require the ability to open new pages. Since the PageFrame class holds the current page, all pages require access to the page frame.

Modify the PageVM constructor to expect another parameter of type PageFrameVM in the constructor and store the value in a new field; encapsulate the field with a property:

namespace SimpleMVVM.ViewModels
{
    public class PageVM : ViewModelBase
    {
        private PageFrameVM _pageFrame;

        public PageVM(ISystemConnector systemConnector, PageFrameVM pageFrame)
            : base(systemConnector)
        {
            _pageFrame = pageFrame;
        }

        public PageFrameVM PageFrame
        {
            get
            {
                return _pageFrame;
            }
            set
            {
                _pageFrame = value;
            }
        }
    }
}

Also modify the constructor of the EditCustomerPageVM class…:

using System;

namespace SimpleMVVM.ViewModels
{
    public class EditCustomerPageVM : PageVM
    {
        public EditCustomerPageVM(ISystemConnector systemConnector, PageFrameVM pageFrame)
            : base(systemConnector, pageFrame)
        {
        }
    }
}

…and the constructor of the MainMenuPageVM class:

using System.Windows;

namespace SimpleMVVM.ViewModels
{
    public class MainMenuPageVM : PageVM
    {
        public MainMenuPageVM(ISystemConnector systemConnector, PageFrameVM pageFrame)
            : base(systemConnector, pageFrame)
        {
            _quitCommand = new RelayCommand(ExecuteQuit, QuitCanExecute);
        }

        // ...
    }
}

And modify the construction of the MainMenuPageVM object in SimpleMVVMApp:

using System.Windows;

namespace SimpleMVVM.ViewModels
{
    public class SimpleMVVMApp
    {
        // ...

        public void Init()
        {
            _pageFrame = new PageFrameVM(_systemConnector);
            MainMenuPageVM mainMenuPage = new MainMenuPageVM(_systemConnector, _pageFrame);
            PageFrame.CurrentPage = mainMenuPage;
        }
    }
}

Note: When things turn more complex, it might be a good idea to decouple PageVM and PageFrameVM by using one (or two) interfaces. But we are keeping things simple for now…

Create a new RelayCommand named ShowEditCustomerPageCommand in MainMenuPageVM:

using System.Windows;

namespace SimpleMVVM.ViewModels
{
    public class MainMenuPageVM : PageVM
    {
        private RelayCommand _quitCommand;
        private RelayCommand _showEditCustomerPageCommand;

        public MainMenuPageVM(ISystemConnector systemConnector, PageFrameVM pageFrame)
            : base(systemConnector, pageFrame)
        {
            _quitCommand = new RelayCommand(ExecuteQuit, QuitCanExecute);
            _showEditCustomerPageCommand = new RelayCommand(ExecuteShowEditCustomerPageCommand, ShowEditCustomerPageCommandCanExecute);
        }

        public RelayCommand QuitCommand
        {
            get
            {
                return _quitCommand;
            }

            set
            {
                _quitCommand = value;
            }
        }

        public RelayCommand ShowEditCustomerPageCommand
        {
            get
            {
                return _showEditCustomerPageCommand;
            }
            set
            {
                _showEditCustomerPageCommand = value;
            }
        }

        private void ExecuteQuit(object o)
        {
            SystemConnector.Quit();
        }

        private void ExecuteShowEditCustomerPageCommand(object o)
        {
        }

        private bool QuitCanExecute(object o)
        {
            return true;
        }

        private bool ShowEditCustomerPageCommandCanExecute(object o)
        {
            return true;
        }
    }
}

Create a new EditCustomerPageVM object in ExecuteShowEditCustomerPageCommand() and assign it to the CurrentPage property of the page frame object:

using System.Windows;

namespace SimpleMVVM.ViewModels
{
    public class MainMenuPageVM : PageVM
    {
        // ...

        private void ExecuteShowEditCustomerPageCommand(object o)
        {
            PageFrame.CurrentPage = new EditCustomerPageVM(SystemConnector, PageFrame);
        }
    }
}

Bind to the new command in MainMenuPage.xaml:

<UserControl x:Class="SimpleMVVM.MainMenuPage"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:SimpleMVVM"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">

    <StackPanel Orientation="Vertical">
        <Button Content="Edit Customers" Command="{Binding ShowEditCustomerPageCommand}"  Style="{StaticResource MainMenuButton}" />
        <Button Content="Edit Products" Style="{StaticResource MainMenuButton}" />
        <Button Content="Calculate Invoice" Style="{StaticResource MainMenuButton}" />
        <Button Content="Quit" Command="{Binding QuitCommand}" Style="{StaticResource MainMenuButton}" />
    </StackPanel>
</UserControl>

We finally need a data template for the page itself in App.xaml:

<DataTemplate DataType="{x:Type VM:EditCustomerPageVM}">
    <View:EditCustomerPage />
</DataTemplate>

If you run the application, the page should display now.