Prism: Retrieve current URI from Prism Xamarin.Forms NavigationService

Created on 4 Jul 2017  路  13Comments  路  Source: PrismLibrary/Prism

I am creating iOS and Android versions of an app using Xamarin.Forms and Prism. The app is used to complete a specific workflow. As the user completes entries on each page, I persist the entered data to local storage.

I want to also save a URI to restore the Prism navigation service to the current screen. Doing so will allow the user to resume the workflow where they left off even if the phone is reset, the app is closed by the OS, etc.

I posted this question to SO and was told the current URI isn't available. I can create a dictionary to map screen keywords to URIs manually if necessary, but I'm hoping to avoid such a brittle solution.

XF help wanted

Most helpful comment

Ohhhh.. Now I understand what you are asking for. Essentially a way to ask the navigation service the current navigation stack. I have actually thought about this feature before but never implemented it. I'll have to think about the best way to do this.

All 13 comments

This is not something that Prism will take on responsibility for. This is application code. You must implement your own mechanism for saving and restoring the last uri of your app when then phone shuts off. You are already persisting the entered data, just throw in the uri with it.

Apologies, I didn't state my question clearly here. How do I retrieve the current full uri, presumably from the Navigation service? I've already handled the persistence. Sorry for the confusion!

Deep linking is awesome. Restoring the app to its previous state in the event of crashes, or after being forced to close due to memory constraints/OS updates/reboots, etc., seems like a natural use of it. Being able to fetch the complete uri for the current navigation stack would make this really easy.

The app I'm working on has a short, mostly fixed navigation path. It is possible to hard code all the possible uri values in this case, but this approach doesn't cut it for a larger or more dynamic app.

    public enum AppPages
    {
        Login,
        ForgotPassword,
        CreateAccountStep1,
        CreatAccountStep2,
        CreateAccountStep3,
        ScanQrCode,
        QrCodeNotWorking,
        SetPhoneNumber,
        ServiceAddress,
        Payment,
        PaymentConfirmation,
        WirelessNetwork,
        WirelessNetworkConfirmation,
        Finished
    }

    private readonly Dictionary<AppPages, string> _pageRestoreUris = new Dictionary<AppPages, string>
    {
        {AppPages.Login, "/NavigationPage/Login"},
        {AppPages.ForgotPassword, "/NavigationPage/Login/ForgotPassword"},
        {AppPages.CreateAccountStep1, "/NavigationPage/Login/CreateAccountStep1"},
        {AppPages.CreatAccountStep2, "/NavigationPage/Login/CreateAccountStep1/CreatAccountStep2"},
        {AppPages.CreateAccountStep3, "/NavigationPage/Login/CreateAccountStep1/CreatAccountStep2/CreatAccountStep3"},
        {AppPages.ScanQrCode, "/NavigationPage/ScanQrCode"},
        {AppPages.QrCodeNotWorking, "/NavigationPage/ScanQrCode/QrCodeNotWorking"},
        {AppPages.SetPhoneNumber, "/NavigationPage/ScanQrCode/SetPhoneNumber"},
        {AppPages.ServiceAddress, "/NavigationPage/ScanQrCode/SetPhoneNumber/ServiceAddress"},
        {AppPages.Payment, "/NavigationPage/ScanQrCode/SetPhoneNumber/ServiceAddress/Payment"},
        {AppPages.PaymentConfirmation, "/NavigationPage/ScanQrCode/SetPhoneNumber/ServiceAddress/Payment/PaymentConfirmation"},
        {AppPages.WirelessNetwork, "/NavigationPage/ScanQrCode/SetPhoneNumber/ServiceAddress/Payment/PaymentConfirmation/WirelessNetwork"},
        {AppPages.WirelessNetworkConfirmation, "/NavigationPage/ScanQrCode/SetPhoneNumber/ServiceAddress/Payment/PaymentConfirmation/WirelessNetwork/WirelessNetworkConfirmation" },
        {AppPages.Finished, "/NavigationPage/Finished"}
    };

    public AppPages CurrentPage { get; set; }
    public Uri CurrentPageUri => new Uri(_pageRestoreUris[CurrentPage]);

Ohhhh.. Now I understand what you are asking for. Essentially a way to ask the navigation service the current navigation stack. I have actually thought about this feature before but never implemented it. I'll have to think about the best way to do this.

Great, thanks so much! Any chance this can be labeled as a future enhancement?

I just came here looking for this exact thing. I was thinking that instead of having it as another method on the Navigation Service, that maybe it could be passed into the NavigationParameters

public void OnNavigatedTo(NavigationParameters parameters)
{
    var currentPath = parameters.GetValue<Uri>("_currentPath"); // should be the absolute path
}

Then you just keep track of it as you navigate around the app, continuing to update and pass the new value.

Yeah, this will be a tricky one. Most likely won't make 7.0

Just an update.. I am making very slow progress on this feature. So far I have the NavigationPage scenario covered. Now, I am working on the more complicated scenarios of a mix of modal and non-modal while throwing in MasterDetailPages, TabbedPages, and NavigationPages. I'm getting confused :)

Done! Feel free to test it out using the latest CI build on MyGet which should be ready in about 15 minutes.

@brianlagunas, thanks so much for getting this one taken care of! I will give it a try and report back if I run into any issues.

Thanks! It will definitely need some testing. There are so many different navigation scenarios, I probably missed something. Let me know if you find anything.

@brianlagunas Hi, I'm not getting in the uri any pages that I navigated to using modal navigation. Is this intentional or am I missing something?

No intentional. That should work. Provide a sample that I can check out.

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings