Search code examples
c#mvvmxamarin.formsprismprism-7

PRISM navigationService is null in ViewModel constructor


SITUATION: I have these objects:

MainMenuView
MainMenuViewModel
MainMenuPage

The MainMenuPage contains the MainMenuView, like so:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:xxx_App.Pages"
             xmlns:views="clr-namespace:xxx_App.Views"
             x:Class="xxx_App.Pages.MainMenuPage">
    <ContentPage.Content>
        <StackLayout>           
            <views:MainMenuView />
        </StackLayout>
    </ContentPage.Content>
</ContentPage>

The MainMenuView is auto wired to the MainMenuViewModel, like this:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             x:Class="xxx_App.Views.MainMenuView">
  <ContentView.Content>
        <StackLayout>
            // SOME BUTTONS
        </StackLayout>
  </ContentView.Content>
</ContentView>

Here is my MainMenuViewModel constructor:

public MainMenuViewModel(INavigationService navigationService)
{
    // A breakpoint here does break the software, but navigationService is null
}

PROBLEM: The problem is that navigationService is null in the MainMenuViewModel's constructor. The constructor DOES get called, so I don't think this is a problem with auto wiring. The constructor gets called by the PRISM framework's auto wiring function.

Does anybody have an idea as to why the navigationService is null?

Thanks in advance!

EDIT:

SOLUTION: I partly used Roubachof's solution.

I created a MainMenuPageViewModel. I got rid of the MainMenuViewModel, since this is not necessary anymore. I moved the ICommands (mentioned in comments) to the new MainMenuPageViewModel.

Clearly I got confused between pages and views when reading about PRISM. I thought a view had a viewmodel, but actually a page has a viewmodel. This happened because MVVM and Xamarin.Forms use different terminology. I'll go and make some changes to my application's structure now that I know this.


Solution

  • I think Prism uses class activation for creating sub view models and not view model locator, it only works for the Page view model.

    But you are using prism:ViewModelLocator.AutowireViewModel="True" in your inner view. So you should use it on your ContentPage, and then have a matching MainMenuPageViewModel, with the injected navigation service.

    In this parent view model you can create your sub view models and pass your dependencies.