You can achieve this by using a single ContentControl and by changing model assigned to its Content property. The base model class looks as follows:
class NavigationViewModel : BaseViewModel
{
public NavigationViewModel PreviousView { get; set; }
public FrameworkElement View { get; set; }
public RelayCommand GoBackCommand { get; private set; }
public string Name { get; private set; }
public RelayCommand<NavigationViewModel> ShowSubItem { get; private set; }
public NavigationViewModel(Action<NavigationViewModel> updateCurrentView, string name)
{
Name = name;
ShowSubItem = new RelayCommand<NavigationViewModel>(view => updateCurrentView(view));
}
}
Then you create specific classes for each view
HomeViewModel (with 4 action items, I created only the first one)
class HomeViewModel : NavigationViewModel
{
public ActionItem1ViewModel Action1 { get; private set; }
public HomeViewModel(Action<NavigationViewModel> updateCurrentView) : base(updateCurrentView, "Home")
{
Action1 = new ActionItem1ViewModel(updateCurrentView)
{
PreviousView = this
};
PreviousView = null;
View = new HomeView();
}
}
and associated view
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="Item #1" Command="{Binding ShowSubItem}" CommandParameter="{Binding Action1}"/>
<Button Content="Item #2" Grid.Column="1"/>
<Button Content="Item #3" Grid.Row="1"/>
<Button Content="Item #4" Grid.Row="1" Grid.Column="1"/>
</Grid>
A single sub-item view model
class ActionItem1ViewModel : NavigationViewModel
{
public Action1SubItemViewModel SubItem { get; private set; }
public ActionItem1ViewModel(Action<NavigationViewModel> updateCurrentView) : base(updateCurrentView, "Item #1")
{
View = new Action1();
SubItem = new Action1SubItemViewModel(updateCurrentView)
{
PreviousView = this
};
}
}
and associated view
<Button Content="Item #1" Command="{Binding ShowSubItem}" CommandParameter="{Binding SubItem}"/>
and sub-item details view model
class Action1SubItemViewModel : NavigationViewModel
{
public Action1SubItemViewModel(Action<NavigationViewModel> updateCurrentView) : base(updateCurrentView, "Sub Item details")
{
View = new SubItem();
}
}
and associated view
<TextBlock Text="details"/>
The MainWindow looks as follows
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Content="{Binding CurrentView.PreviousView.Name}" Command="{Binding GoBackCommand}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Visible"/>
<Style.Triggers>
<DataTrigger Binding="{Binding CurrentView.PreviousView}" Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<ContentControl Grid.Row="1" Content="{Binding View}" DataContext="{Binding CurrentView}" Margin="50"/>
</Grid>
and its view model
class MainViewModel : BaseViewModel
{
private NavigationViewModel _currentView;
public NavigationViewModel CurrentView
{
get => _currentView;
set
{
_currentView = value;
OnPropertyChanged();
}
}
public RelayCommand GoBackCommand { get; private set; }
public MainViewModel()
{
CurrentView = new HomeViewModel(UpdateCurrentView);
GoBackCommand = new RelayCommand(() =>
{
CurrentView = CurrentView.PreviousView;
});
}
private void UpdateCurrentView(NavigationViewModel viewModel)
{
CurrentView = viewModel;
}
}
