0

I have a UWP app which has 3 pages and third page contains a frame tag which loads multiple frames. Lets say I navigate to page 1->page 2-> Page 3->Frame 1-> Frame 2->Frame 3. If I press back button from frame 3 and 2 it goes to page 2 instead of frame 2 and frame 1 respectively. I have a common method to handle the back button event and it takes the root frame which is same for frame 1,2 and 3 which is page 3 and goes back to its back page page 2. So how can I go back to frames instead of the root page back. Below is the common back method I have in App.xaml.cs. Please help.

  protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;
        Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += App_BackRequested;

        }
    }


    private void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
    {
        e.Handled = On_BackRequested();
    }



    private bool On_BackRequested()
    {
        Frame rootFrame = Window.Current.Content as Frame;



        if (rootFrame.CanGoBack)
        {
            rootFrame.GoBack();
            return true;
        }
        return false;
    }

public HomeView()
    {
        this.InitializeComponent();
        var vm = new HomeViewModel(new UserService(), new SubscriptionService(), new TransactionService(),new GameService());
        this.DataContext = vm;
        WalletBtn.Foreground = new SolidColorBrush(Colors.White);
        PaymentGrid = BuyModal;
        //PowerPassGameListGrid = PowerPassGameGrid;
       // SystemNavigationManager.GetForCurrentView().BackRequested += HomePage_BackRequested;
        PointBalance = wallet;
        //QueuedGames = QueueGame;
        //PowerPassSubscriptionGrid = PowerPass;
        SubmitPopUp = SuccessPopUp;
        RecentActivityGrid = RecentActivityModel;
        CurrentlyPickedPopUp = GamePickUp;
        PowerUpNavigationGrid = NavigationGrid;
    }
    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        string firstName = (string)ApplicationData.Current.LocalSettings.Values["FirstName"];
        string lastName = (string)ApplicationData.Current.LocalSettings.Values["LastName"];
        if (firstName != null && lastName != null)
        {
            welcomeMessage.Text = "Hi, " + firstName;
        }
    }
    public void MyWalletButton_Click(object sender, RoutedEventArgs e)
    {
        PowerPassBtn.Foreground = new SolidColorBrush(Colors.Gray);
        WalletBtn.Foreground = new SolidColorBrush(Colors.White);       
    }
    public void PowerPassButton_Click(object sender, RoutedEventArgs e)
    {
        PowerPassSelection();
    }

    //private void HomePage_BackRequested(object sender, BackRequestedEventArgs e)
    //{
    //    e.Handled = true;
    //    this.Frame.Navigate(typeof(LoginUsernameView));
    //}
    private void ButtonGotFocus(object sender, RoutedEventArgs e)
    {
        (sender as Button).Background = new SolidColorBrush(Colors.Green);
    }

    private void ButtonLostFocus(object sender, RoutedEventArgs e)
    {
        (sender as Button).Background = new SolidColorBrush(Colors.Transparent);
    }

    private void QueueButtonGotFocus(object sender, RoutedEventArgs e)
    {
        (sender as Button).Background = new SolidColorBrush(Colors.DeepSkyBlue);
    }

    private void QueueButtonLostFocus(object sender, RoutedEventArgs e)
    {
        (sender as Button).Background = new SolidColorBrush(Colors.Transparent);
    }

    private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
    {
        var parent = VisualTreeHelper.GetParent(dependencyObject);
        if (parent == null) return null;

        var parentT = parent as T;
        return parentT ?? FindParent<T>(parent);
    }
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        NavigationParameterDTO parameter = e.Parameter as NavigationParameterDTO;
        if (parameter != null)
        {
            if (parameter.FrameName == "WelcomeView")
            {
                HomeViewModel vm = this.DataContext as HomeViewModel;
                vm.PowerPassWelcomeFrame.Execute(null);
                PowerPassSelection();
            }
            else if(parameter.FrameName == "CheckOut")
            {
                HomeViewModel vm = this.DataContext as HomeViewModel;
                vm.PowerPassGameCheckOutMethod.Execute(null);
                PowerPassSelection();
            }
            else if(parameter.FrameName== "SignUp")
            {
                HomeViewModel vm = this.DataContext as HomeViewModel;
                vm.PowerPassFrame.Execute(null);
                PowerPassSelection();
            }
            else
            {
                HomeViewModel vm = this.DataContext as HomeViewModel;
                vm.PowerPassHomeFrame.Execute(null);
                PowerPassSelection();
            }
        }
    }

Xaml

                   <Button Style="{StaticResource PowerUpButtonStyle}"  x:Uid="Profile"  FontSize="36" Margin="0,60,0,0" Name="SettingsBtn" XYFocusDown="{x:Bind SettingsBtn}" FontFamily="Segoe Pro" Foreground="Gray" FocusVisualPrimaryThickness="0,0,0,3" FocusVisualMargin="10,0">
                        <Button.Background>
                            <SolidColorBrush Opacity="0"/>
                        </Button.Background>
                        <Button.Resources>
                            <ResourceDictionary>
                                <ResourceDictionary.ThemeDictionaries>
                                    <ResourceDictionary x:Key="Light">
                                        <SolidColorBrush x:Key="ButtonForegroundPointerOver" Color="White"/>
                                    </ResourceDictionary>
                                </ResourceDictionary.ThemeDictionaries>
                            </ResourceDictionary>
                        </Button.Resources>
                    </Button>
                </StackPanel>
                <Image Source="/Assets/Images/PURlogo_large.png" HorizontalAlignment="Left"  Margin="70,950" Width="212" Height="78"/>
            </Grid>
        </StackPanel>
        <Frame x:Name="MainFrame" Grid.Column="1" Content="{Binding FrameData,Mode=OneWay}" >
        </Frame>
        <Grid Background="Red" Visibility="Collapsed" x:Name="testgrid">
            <TextBlock Text="hello world"></TextBlock>
        </Grid>
    </Grid>
sadik
  • 107
  • 10
  • Can you explain how is the app structured? Do you actually have three different Frames? Or what is the distinction? Because you can't navigate from page to a frame and from a frame to another frame as described in the question – Martin Zikmund Oct 16 '18 at 09:49
  • I have 3 views and the third view contains the frames. First two pages are for login and the third page is the home page where there is a common menu and frame which changes according to the menu selection. – sadik Oct 16 '18 at 10:16
  • But then you have just single Frame on the last page, not three different ones, isn't that correct? My answer should be valid for this – Martin Zikmund Oct 16 '18 at 10:19
  • Sorry I am fairly new to the UWP. I mean frames will be loaded as if like a single page application. – sadik Oct 16 '18 at 10:27
  • Check my answer to see if that fits the issue or I can assist further :-) – Martin Zikmund Oct 16 '18 at 10:28

1 Answers1

2

Using Window.Current.Content gives you the very root Frame of the app. If you want to check if the Page3 is currently open and utilize its frames, you will have to do something like:

private bool On_BackRequested()
{
    Frame rootFrame = Window.Current.Content as Frame;

    if (rootFrame.Content is Page3 page3 )
    {
         var innerFrame = page3.GetInnerFrame(); //implement this method in Page3
         if (innerFrame.CanGoBack)
         {
             innerFrame.GoBack();
             return true;
         }
    } 

    if (rootFrame.CanGoBack)
    {
        rootFrame.GoBack();
        return true;
    }
    return false;
}

The GetInnerFrame method will be in Page3 code-behind and will just return the frame that is on the page.

The code above will just navigate back with the frame that is within the Page3. If you nest further, you will again have to work with this frame's Content and so on.

Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
  • Can you please show how to implement the GetInnerFrame method? I am new to this and it would be of great help – sadik Oct 16 '18 at 10:38
  • Could you post the XAML source code of the third page? (you can edit the question and add it there) – Martin Zikmund Oct 16 '18 at 10:41
  • Can ypou show me how to implement GetInnerFrame Method? – sadik Oct 17 '18 at 11:51
  • Sorry, I can, but first what are `vs.PowerPassFrame.Execute(null)`, `vm.PowerPassHomeFrame.Execute(null)` etc doing? Could you provide source code for those? – Martin Zikmund Oct 17 '18 at 11:56
  • That's basically executing commands in the view model based of the pages. If its a welcome view some functions needs to be executed etc. – sadik Oct 17 '18 at 12:01
  • But where do you actually access or navigate in any of the frames you have mentioned? Could you also post XAML of the page if possible? I still don't really understand why you need multiple frames and how you use them, it would be really helpful to see it. – Martin Zikmund Oct 17 '18 at 12:09
  • its not multiple frames.. I have a frame which loads the pages and couple of pages that doesnt contain frames. The pages without the frame back navigation is working as expected. But in the page with frame, If I press back button instead of showing the page loaded previously in the frame it goes to the previous root page. I have added the xaml. – sadik Oct 17 '18 at 12:15
  • I see you are using Binding to set content of the frame, but that is not the right way to use frame, because it means it doesn't store navigation history and hence you cannot go back in the frame. You should use MainFrame.Navigate to navigate between pages – Martin Zikmund Oct 17 '18 at 12:43
  • Okay let me try that – sadik Oct 23 '18 at 08:59
  • I have used MainFrame.Navigate and the back navigation in frames is working fine.I have another issue though, I have a frame which navigates to a page and while clicking back its going back to the page where the frame is loaded instead of the frame. Anyway to fix that? Thanks – sadik Oct 30 '18 at 12:38
  • I would suggest closing this question as resolved and creating a new one with the updated source code, because it is a different problem and the thread is getting quite long – Martin Zikmund Oct 30 '18 at 12:41