Graeme_Grant
Взгляните на MVVM Light Toolkit[^]- Эта библиотека упрощает ряд концепций MVVM, включая команды.
Например, я использую элемент управления кадром для размещения двух моих тестовых навигационных представлений:
<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 для главного окна
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);
}
}
}
И две страницы (навигационные представления)
<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>
Теперь я могу нажать на кнопки, и вид изменится.
Обновление
Прочитав еще раз ваш вопрос, я понимаю, что вам могут понадобиться только навигационные кнопки на дочерних представлениях. Итак, вот еще одно решение, использующее Mvvmlight Messaging. Система обмена сообщениями обеспечивает простую связь между представлениями.
Главное окно:
<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 для главного окна
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);
}
}
}
Класс обмена сообщениями, используемый для передачи типизированных сообщений между моделями представления
namespace WpfApp1
{
public class MenuNavigationMessage
{
public MenuNavigationMessage(string msg)
{
Message = msg;
}
public string Message { get; }
}
}
Базовая модель представления для навигационных представлений с общей функциональностью-сообщениями и кнопками:
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; }
}
}
И две страницы (навигационные представления)
<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>
И viewmodels для страниц
namespace WpfApp1
{
public class Page1ViewModel : NavigationViewModelBase
{
}
public class Page2ViewModel : NavigationViewModelBase
{
}
}
Теперь кнопки навигации находятся на каждой странице. Щелчок по ним переключит вид.