I know this question was posted long ago, but recently I stumbled upon similar issue and this is how I solved it for my case. I hope it'll help someone.
Requirement
User should be able to go back to pages visited earlier but should not be able to go forward once back button is pressed.
My Approach
Create a custom control derived from Frame
and add two addition DPs AllowForwardNavigation
and AllowBackNavigation
so that I can control if I want to allow prev/next navigation.
MyFrame.xaml.cs
public partial class MyFrame : Frame
{
#region Dependency Properties
public bool AllowForwardNavigation
{
get { return (bool)GetValue(AllowForwardNavigationProperty); }
set { SetValue(AllowForwardNavigationProperty, value); }
}
public static readonly DependencyProperty AllowForwardNavigationProperty =
DependencyProperty.Register(nameof(AllowForwardNavigation), typeof(bool), typeof(MyFrame), new PropertyMetadata(true));
public bool AllowBackNavigation
{
get { return (bool)GetValue(AllowBackNavigationProperty); }
set { SetValue(AllowBackNavigationProperty, value); }
}
public static readonly DependencyProperty AllowBackNavigationProperty =
DependencyProperty.Register(nameof(AllowBackNavigation), typeof(bool), typeof(MyFrame), new PropertyMetadata(true));
#endregion
public MyFrame()
{
InitializeComponent();
JournalOwnership = JournalOwnership.OwnsJournal;
// find existing bindings
var existingBindings = CommandBindings.OfType<CommandBinding>()
.Where(x => x.Command == NavigationCommands.BrowseForward
|| x.Command == NavigationCommands.BrowseBack)
.ToArray();
// remove existing bindings
foreach (var binding in existingBindings)
CommandBindings.Remove(binding);
// add new binding
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseForward, OnGoForward, OnQueryGoForward));
CommandBindings.Add(new CommandBinding(NavigationCommands.BrowseBack, OnGoBack, OnQueryGoBack));
// override default navigation behavior
NavigationService.Navigating += NavigationService_Navigating;
}
private void NavigationService_Navigating(Object sender, NavigatingCancelEventArgs e)
{
switch (e.NavigationMode)
{
case NavigationMode.Forward:
e.Cancel = !AllowForwardNavigation;
break;
case NavigationMode.Back:
e.Cancel = !AllowBackNavigation;
break;
}
}
#region Command methods
private void OnGoForward(Object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
if (AllowForwardNavigation && NavigationService.CanGoForward)
NavigationService.GoForward();
}
private void OnQueryGoForward(Object sender, CanExecuteRoutedEventArgs e)
{
e.Handled = true;
e.CanExecute = AllowForwardNavigation && NavigationService.CanGoForward;
}
private void OnGoBack(Object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
if (AllowBackNavigation && NavigationService.CanGoBack)
NavigationService.GoBack();
}
private void OnQueryGoBack(Object sender, CanExecuteRoutedEventArgs e)
{
e.Handled = true;
e.CanExecute = AllowBackNavigation && NavigationService.CanGoBack;
}
#endregion
}
MyFrame.xaml
<Style x:Key="NavigationWindowBackButtonStyle" TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Command" Value="NavigationCommands.BrowseBack"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="Transparent" Height="24" Width="24">
<Ellipse x:Name="Circle" Fill="{StaticResource NavigationWindowNavigationButtonFillEnabled}" Stroke="{StaticResource NavigationWindowNavigationButtonStrokeEnabled}" StrokeThickness="1"/>
<Path x:Name="Arrow" Data="M0.37,7.69 L5.74,14.20 A1.5,1.5,0,1,0,10.26,12.27 L8.42,10.42 14.90,10.39 A1.5,1.5,0,1,0,14.92,5.87 L8.44,5.90 10.31,4.03 A1.5,1.5,0,1,0,5.79,1.77 z" Fill="{StaticResource NavigationWindowNavigationArrowFill}" HorizontalAlignment="Center" Stroke="{StaticResource NavigationWindowNavigationArrowStrokeEnabled}" StrokeThickness="0.75" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillDisabled}"/>
<Setter Property="Stroke" TargetName="Circle" Value="#B5BACE"/>
<Setter Property="Stroke" TargetName="Arrow" Value="#B0B5BACE"/>
<Setter Property="Fill" TargetName="Arrow" Value="#D0FFFFFF"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillHover}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillPressed}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="NavigationWindowForwardButtonStyle" TargetType="{x:Type Button}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Command" Value="NavigationCommands.BrowseForward"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="Transparent" Height="24" Width="24">
<Ellipse x:Name="Circle" Grid.Column="0" Fill="{StaticResource NavigationWindowNavigationButtonFillEnabled}" Stroke="{StaticResource NavigationWindowNavigationButtonStrokeEnabled}" StrokeThickness="1"/>
<Path x:Name="Arrow" Grid.Column="0" Data="M0.37,7.69 L5.74,14.20 A1.5,1.5,0,1,0,10.26,12.27 L8.42,10.42 14.90,10.39 A1.5,1.5,0,1,0,14.92,5.87 L8.44,5.90 10.31,4.03 A1.5,1.5,0,1,0,5.79,1.77 z" Fill="{StaticResource NavigationWindowNavigationArrowFill}" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0" Stroke="{StaticResource NavigationWindowNavigationArrowStrokeEnabled}" StrokeThickness="0.75" VerticalAlignment="Center">
<Path.RenderTransform>
<ScaleTransform ScaleX="-1"/>
</Path.RenderTransform>
</Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillDisabled}"/>
<Setter Property="Stroke" TargetName="Circle" Value="#B5BACE"/>
<Setter Property="Stroke" TargetName="Arrow" Value="#B0B5BACE"/>
<Setter Property="Fill" TargetName="Arrow" Value="#D0FFFFFF"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillHover}"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Fill" TargetName="Circle" Value="{StaticResource NavigationWindowNavigationButtonFillPressed}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Frame.Resources>
<Frame.Template>
<ControlTemplate TargetType="Frame">
<DockPanel Margin="7">
<StackPanel Visibility="{TemplateBinding NavigationUIVisibility}" Margin="0" Orientation="Horizontal"
DockPanel.Dock="Top">
<Button Style="{StaticResource NavigationWindowBackButtonStyle}"
Command="NavigationCommands.BrowseBack"
Content="M 4 0 L 0 4 L 4 8 Z"
Margin="2.7,0,1.3,0" />
<Button Style="{StaticResource NavigationWindowForwardButtonStyle}"
Command="NavigationCommands.BrowseForward"
Content="M 4 0 L 0 4 L 4 8 Z" Margin="1.3,0,0,0" />
</StackPanel>
<Border>
<ContentPresenter />
</Border>
</DockPanel>
</ControlTemplate>
</Frame.Template>
</Frame>
Usage
<local:MyFrame x:Name="_mainFrame" NavigationUIVisibility="Visible"
AllowForwardNavigation="False" />