3
votes

I have problem how to implement sub-page navigation in UWP. The page is in RootFrame, which I can use on navigation. But i want to use something like this:

    <Page>
<Grid>
 <Frame x:Name="MyFrame"/>
</Grid>
</Page>

What I want is, use Navigate method of control MyFrame in ViewModel. I can call the method from code-behind, but I'm developing my app using MVVM. I'm not sure, if Template10 can work with sub-frames.

I appreciate any advice.

EDIT: More details: I have pivot control which is in page. the pivot has 2 tabs (pivotitems). The content of the pivotitem must be navigable. What I mean: I pivotitem 1, I need to have one Frame and use it for navigation in the pivotitem. My problem is, how to use or how to call the frame in pivotitem from ViewModel, especially I need to call Navigate method. Now I'm using Template10's navigation service and it's working with rootframe. I don't know, how to use it for other let's say sub-frames.

4

4 Answers

5
votes

You can always do this.

var nav = Bootstrapper.NavigationServiceFactory(BackButton.Attach, ExistingContent.Exclude, this.Frame);

This will give you a navigation service for the frame in your page. You can then use session state, if you like.

Bootstapper.SessionState["MyNav"] = nav;

From here your view-model can access the service and navigate. You can repeat this for as many frames as you have. And you can then handle navigation in your view-model without consideration of "where" the frame is, just that your logic requires it to nav.

Does this make sense?

2
votes

I don't know how you are going to trigger the navigation change so I'll assume it will start from a button click. I am also assuming the button's Command property is already bound to an ICommand in the viewmodel (the same concepts can be applied to different kinds of views).

All we have to do now is to make the ICommand implementation call our custom NavigationService to perform the content switch. This NavigationService class will be nothing but a simple proxy to the window global frame. Its main navigation method can be as simples as:

    public void Switch()
    {
        var rootFrame = Window.Current.Content as Frame;

        if ((rootFrame.Content as ParentPage) != null)
        {
            rootFrame.Navigate(typeof(ChildPage));   
        }
    }
2
votes

So you have tagged this with Template10 but it seems to be a more general question for UWP as a whole. I wonder if you have considered all of the inherent complexities with this approach - specifically related to suspension and resume. For each frame you have, you would need to save and restore navigation state, which isn't straight-forward when you have nested frames. Have you also considered how global navigation would work?

Template 10 does support the concept of multiple NavigationServices and, therefore, multiple frames, but only from the perspective of you can create them. Template10 does not inherently understand how such frames may be related to each other, so cannot perform automatic back propagation where you have something like:

FrameA[Main->Page1->Page1:Pivot1.FrameB[View1->View2->View3]]

Here we have two frames - FrameA and FrameB. FrameA has navigated from Main to Page1. Page1 has a Pivot that hosts FrameB in PivotItem1 and FrameB has navigated from View1 to View 2 and from View2 to View 3.

Global navigation (i.e. the shell back, etc.) would be automatically wired to FrameA, so you would need to intercept that action, and then handle you own navigation activity for FrameB.

Take a look at the BackButtonBehavior to see how it is possible to intercept the global back and then put in place your own action.

1
votes

I don't know if you can do something like that.. One possible workaround is to use a Messenger that sends a message from your viewmodel to the view's code behind.. I'm not a fan of this solution though, because as I said before you have to use the page's code behind..