Registering an instance for navigation in Prism for Xamarin Forms with Unity

1.4k Views Asked by At

I'd like to register an instance of a view for navigation in Prism for Xamarin Forms with Unity and receive OnNavigatedTo on the associated view model when navigating to the instance. Registering an instance for navigation is not a supported registration out of the box so I created the following extension:

      public static void RegisterInstanceForNavigation<TView, TViewModel>(this IUnityContainer container, TView instance, string name = null)
        where TView : Page
        where TViewModel : class
      {
        if (string.IsNullOrWhiteSpace(name))
        {
            name = typeof(TView).Name;
        }

        ViewModelLocationProvider.Register(typeof(TView).ToString(), typeof(TViewModel));
        PageNavigationRegistry.Register(name, typeof(TView));
        container.RegisterInstance(typeof(object), name, instance, new ContainerControlledLifetimeManager());
     }

In my app.xaml.cs, RegisterTypes, I register a page for navigation:

this.Container.RegisterInstanceForNavigation<AwesomeView, AwesomeViewModel>(
    new AwesomeView(),
    "seriouslyAnAwesomeView")

This seems to partially work. I can create an instance of a page, register it with a name and navigate to it. On the first navigation the corresponding view model's OnNavigatedTo from INavigationAware gets called; however, in subsequent navigation to the page, OnNavigatedTo is not called.

Is this registration valid? If so, why wouldn't OnNavigatedTo be called? If not, how can an instance be registered for navigation?

1

There are 1 best solutions below

0
On BEST ANSWER

When the user presses the back button, Prism destroys the page and unsets the BindingContext. Prism only sets the BindingContext once at creation, if auto-wiring is enabled. Thus, the next time Prism navigates to your page, the binding context is null and OnNaviagedTo never gets called.

As mentioned in the comments above, keeping views around in memory is somewhat atypical behavior, and it appears that this behavior is not formally supported by Prism.

That being said, you can fix this issue fairly easily by resetting the binding context on the Pagemanually. Prism allows you to make your Page navigation aware like so:

public class MyReusablePage : ContentPage, INavigationAware
{
    ...

    public void OnNavigatingTo(NavigationParameters parameters)
    {
        if (this.BindingContext == null)
        {
            this.BindingContext = new MyReusablePageViewModel();
        }
    }

    ...
}

Be wary that the new view model instance will NOT be identical to the one Prism originally created for you. If you need the view model instance to never change as well, you will need to disable auto-wiring (AutoWireViewModel="False" in XAML) and register your own singleton instance with Unity.