NavigationService remove forwardstack
Asked Answered
B

1

10

I see a lot of answers, about removing the backstack.

But How do I remove the forward stack?

Aka, Navigating A, to B, to C

A -> B -> C

I then navigate back from C, to B (Form saved, C closed NavigationService.GoBack();)

B <- C

I should now, NOT be able to navigate back to C using the forward button. But have no idea how to implement this. It makes most sense to remove it from the stack somehow.

Boltonia answered 16/11, 2016 at 10:12 Comment(11)
Does anyone know how to achieve this? Still struggling with it.Boltonia
Just an idea - when you in B and you somehow know you're back from C, repeat the navigation to B. This should make B the most recent visited element so no way to go to C. Once again, just an idea - didn't give it a try.Prosit
@AlexSeleznyov Thanks for your suggestion. I have checked if CanGoForward then navigate to a copy of itself (B2), and remove the backstack to remove the origional B. It seems like a hacky implementation. As it is essentially having to reload B. But i was reloading the data on the page anyway So not a massive hit. It is a solution, but wonder if there is a better one. Glad its working at least. Thanks!Boltonia
You might also want to dig into NavigationService code - I recall there is a dependency property CanGoForward and some logic around its state so it might worth trying to set that property directly to false. An idea, again.Prosit
Did you see this question: https://mcmap.net/q/1169413/-remove-forward-entry-on-navigation-service/656243 .. it seems to be exactly what you're looking for.Farnesol
@LynnCrumbling None of the answers remove from the forward stack. And some answers don't work. I'm guessing its not possible, so I'll go with alternative functionality.Boltonia
did you try to handle navigation event? I mean just cancel navigation forward. NavigatingCancelEventArgs e; if (e.NavigationMode == NavigationMode.Forward) e.Cancel = true;Marji
@Marji The arrow will still show it possible to go forward on navigation bar though?Boltonia
have you tried cancelling it AND this? #6368376Grania
Thanks for all the suggestions. I'll give it all a try.Boltonia
@Doomsknight Page.goForwardButton.IsEnabled = false;Marji
A
0

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" />
Almanza answered 21/8, 2018 at 18:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.