Have a look at
MVVM Light Toolkit[
^] - This library simplifies a number of MVVM concepts including commands.
For Example, I am using a Frame control to host my two test navigation views:
<Window
x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
Title="WPF Navigation Example" Height="350" Width="525">
<Window.Resources>
<Style x:Key="FrameStyle1" TargetType="{x:Type Frame}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="NavigationUIVisibility" Value="Hidden" />
<Setter Property="Margin" Value="0" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Frame}">
<ContentPresenter x:Name="PART_FrameCP"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<DockPanel>
<Border DockPanel.Dock="top" Background="AliceBlue" Padding="10">
<StackPanel Orientation="Horizontal" >
<Button Content="Page1" Padding="10 5" Margin="0 0 10 0"
Command="{Binding MenuCommand}" CommandParameter="Page1"/>
<Button Content="Page2" Padding="10 5" Margin="0 0 10 0"
Command="{Binding MenuCommand}" CommandParameter="Page2"/>
</StackPanel>
</Border>
<Frame Source="{Binding NavigateTo}" Style="{StaticResource FrameStyle1}" />
</DockPanel>
</Window>
ViewModel for the MainWindow
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.CommandWpf;
namespace WpfApp2
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
MenuCommand = new RelayCommand<string>(msg => NavigateTo = $"{msg}.xaml");
}
public RelayCommand<string> MenuCommand { get; }
private string navigateTo = "Page1.xaml";
public string NavigateTo
{
get => navigateTo;
set => Set(ref navigateTo, value);
}
}
}
And the two Pages (Navigation Views)
<Page x:Class="WpfApp2.Page1"
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:WpfApp2"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Grid>
<Viewbox>
<TextBlock Text="Page 1"/>
</Viewbox>
</Grid>
</Page>
<Page x:Class="WpfApp2.Page2"
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:WpfApp2"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page2">
<Grid>
<Viewbox>
<TextBlock Text="Page 2"/>
</Viewbox>
</Grid>
</Page>
Now I can click on the buttons and the view will change.
Update
Having another read of your question I realise that you may only want the navigation buttons on the child views. So here is another solution using MVVMLight Messaging. The Messaging system enables simple communication between the views.
MainWindow:
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
Title="WPF Navigation Example 2" Height="350" Width="525">
<Window.Resources>
<Style x:Key="FrameStyle1" TargetType="{x:Type Frame}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="NavigationUIVisibility" Value="Hidden" />
<Setter Property="Margin" Value="0" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Frame}">
<ContentPresenter x:Name="PART_FrameCP"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<DockPanel>
<Frame Source="{Binding NavigateTo}" Style="{StaticResource FrameStyle1}" />
</DockPanel>
</Window>
ViewModel for the MainWindow
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
namespace WpfApp1
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
Messenger.Default.Register<MenuNavigationMessage>
(
this,
(navMsg) => NavigateTo = $"{navMsg.Message}.xaml"
);
}
private string navigateTo = "Page1.xaml";
public string NavigateTo
{
get => navigateTo;
set => Set(ref navigateTo, value);
}
}
}
The Messaging class used to pass typed messages between the viewmodels
namespace WpfApp1
{
public class MenuNavigationMessage
{
public MenuNavigationMessage(string msg)
{
Message = msg;
}
public string Message { get; }
}
}
A base view model for the navigation views with common functionality - messaging and buttons:
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
namespace WpfApp1
{
public abstract class NavigationViewModelBase : ViewModelBase
{
public NavigationViewModelBase()
{
MenuCommand = new RelayCommand<string>(msg => Messenger.Default.Send(new MenuNavigationMessage(msg)));
}
public RelayCommand<string> MenuCommand { get; }
}
}
And the two Pages (Navigation Views)
<Page x:Class="WpfApp1.Page1"
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:WpfApp1"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
Title="Page1">
<Page.DataContext>
<local:Page1ViewModel/>
</Page.DataContext>
<Grid>
<Button Content="Go to Page2" Padding="10 5" Margin="10"
HorizontalAlignment="left" VerticalAlignment="Top"
Command="{Binding MenuCommand}" CommandParameter="Page2"/>
<Viewbox>
<TextBlock Text="Page 1"/>
</Viewbox>
</Grid>
</Page>
<Page x:Class="WpfApp1.Page2"
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:WpfApp1"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Title="Page2">
<Page.DataContext>
<local:Page2ViewModel/>
</Page.DataContext>
<Grid>
<Button Content="Go to Page1" Padding="10 5" Margin="10"
HorizontalAlignment="left" VerticalAlignment="Top"
Command="{Binding MenuCommand}" CommandParameter="Page1"/>
<Viewbox>
<TextBlock Text="Page 2"/>
</Viewbox>
</Grid>
</Page>
And the viewmodels for the pages
namespace WpfApp1
{
public class Page1ViewModel : NavigationViewModelBase
{
}
public class Page2ViewModel : NavigationViewModelBase
{
}
}
Now the navigation buttons are on each page. Clicking on them will switch the view.