Click here to Skip to main content
15,886,362 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have a problem with navigating with an MvvmCross navigation command which has a button binding. I'm currently testing my code on Android. I want to navigate on a button click, and using the IMvxNavigationService to Navigate to the next ViewModel, which I have set up a command and created a binding

It gives me the Exception: Default [Error] MvxAsyncCommand : exception executing taskSystem.NullReferenceException: Object reference not set to an instance of an object.

It looks like its the IMvxNavigationService Navigate itself that is giving the NullReferenceException and that there's no problem the way I have set up the command.

Android logs:
pixel_2_q_10_0_-_api_29	Error	32148	Default	[Error] MvxAsyncCommand : exception executing taskSystem.NullReferenceException: Object reference not set to an instance of an object.
  at MvxFuelPriceCalculator.Core.ViewModels.FuelPriceCalcViewModel.<get_NavigateCommand>b__56_0 () [0x00000] in C:\Users\Work & Education\Documents\Programming\MvxFuelPriceCalculator\src\MvxFuelPriceCalculator.Core\ViewModels\FuelPriceCalcViewModel.cs:216 
  at MvvmCross.Commands.MvxAsyncCommandBase.ExecuteConcurrentAsync (System.Object parameter, System.Boolean hideCanceledException06-22 13:23:16.852 E/Default (32148):   at MvvmCross.Commands.MvxAsyncCommand+<>c__DisplayClass2_0.<.ctor>b__0 (System.Threading.CancellationToken _) [0x00000] in /_/MvvmCross/Commands/MvxAsyncCommand.cs:190 
  at MvvmCross.Commands.MvxAsyncCommand.ExecuteAsyncImpl (System.Object parameter) [0x00000] in /_/MvvmCross/Commands/MvxAsyncCommand.cs:208
  at MvvmCross.Commands.MvxAsyncCommandBase.ExecuteAsync (System.Object parameter, System.Boolean hideCanceledException) [0x00040] in /_/MvvmCross/Commands/MvxAsyncCommand.cs:88
  at MvvmCross.Commands.MvxAsyncCommandBase.Execute (System.Object parameter) [0x00030] in /_/MvvmCross/Commands/MvxAsyncCommand.cs:70

FirstViewModel.cs
C#
using System.Threading.Tasks;
using System.Windows.Input;
using MvvmCross.Commands;
using MvvmCross.ViewModels;
using MvxFuelPriceCalculator.Core.Services;
using MvvmCross.Navigation;

namespace MvxApplication.Core.ViewModels
{
    public class FirstViewModel : MvxViewModel
    {
        public override async Task Initialize()
        {
            await base.Initialize();
        }

        private readonly IMvxNavigationService _navigationService;

        public FirstViewModel(IMvxNavigationService navigationService)
        {
            _navigationService = navigationService;
        }

        private IMvxAsyncCommand _navigateCommand;
        public IMvxAsyncCommand NavigateCommand
        {
            get
            {   // Breakes here 
                _navigateCommand = _navigateCommand ??
                new MvxAsyncCommand(() => 
                _navigationService.Navigate<SecondViewModel>());
                return _navigateCommand;
            }
        }
    }
}

SecondViewModel.cs
C#
using MvvmCross.ViewModels;

namespace MvxApplication.Core.ViewModels
{
    public class SecondViewModel : MvxViewModel
    {

    }
}

FirstView.cs
C#
using Android.Text;
using Android.Util;
using Android.Views;
using Android.Widget;
using MvvmCross.Platforms.Android.Views;
using MvxApplication.Core.ViewModels;

namespace MvxApplication.Droid.Views
{
    [Activity(Label = "", MainLauncher = false)]
    public class FirstView : MvxActivity<FirstViewModel>
    {

        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.first_layout);

            RelativeLayout relativeLayout = FindViewById<RelativeLayout> 
            (Resource.Id.relativeLayout);
        }
    }
}

first_layout.axml
axml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/design_dark_default_color_background" >

    <Button android:id="@+id/top_bar_btn"
        android:layout_width="180dp"
        android:layout_height="40dp"
        android:layout_marginTop="50dp"
        android:layout_centerHorizontal="true"
        android:clickable="true"
        local:MvxBind="Click NavigateCommand"/>
</RelativeLayout>

SecondView.cs
C#
using Android.App;
using Android.OS;
using MvvmCross.Platforms.Android.Views;
using MvxApplication.Core.ViewModels;

namespace MvxApplication.Droid.Views
{
    [Activity(Label = "Second View", MainLauncher = false)]
    public class SecondView : MvxActivity<SecondViewModel>
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView(Resource.Layout.second_layout);
        }
    }
}

second_layout.axml
axml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:id="@+id/relativeLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/design_dark_default_color_background" >

    <ImageView 
        android:layout_width="match_parent"
        android:layout_height="110dp" 
        android:src="@drawable/rectangle_light"/>
</RelativeLayout>


What I have tried:

I've followed the documentations, on Navigation and Extra - Navigation. And I've looked at some previous posts which haven't helped much.

I have checked the binding and also tried binding it programatically.

I also tried doing this from this post
C#
public class SecondViewModel : MvxViewModel<FirstViewModel>

Which just gives this error
Error	CS0534	'SecondViewModel' does not implement inherited abstract member 'MvxViewModel<FirstViewModel>

Thanks for any help I can get
Posted
Updated 23-Jun-22 2:19am
v2

1 solution

As I looked for more information to write in my question I noticed the IMvxNavigationService function was never run through, this code:
C#
private readonly IMvxNavigationService _navigationService;

public FirstViewModel(IMvxNavigationService navigationService)
{
    _navigationService = navigationService;
}

So my problem got solved by moving it to the top, I thought this worked because the application didn't get to the code before. But as @RichardDeeming wrote, it shouldn't change much. So this may not work for everyone

But there you have my solution

Future Edit: First of all I'm still very much a beginner.
I didn't include enough code. I also had an ICalculationService. And I did have initializer. Turns out you just merge two services into one member/function.

C#
private readonly IMvxNavigationService _navigationService;
private readonly ICalculationService _calculationService;

public FirstViewModel(IMvxNavigationService navigationService, ICalculationService calculationService)
{
     _navigationService = navigationService;
     _calculationService = calculationService;
}
 
Share this answer
 
v3
Comments
Richard Deeming 23-Jun-22 8:26am    
The order of members in your class is (mostly) irrelevant.

The only time it matters is if you have field initializers which depend on other field initializers.

None of the code you have shown has a field initializer. Moving the field and constructor further up the file will not make any difference.

You may have solved your problem, but you have come to the wrong conclusion about what the solution actually was.
ThommyaVV 23-Jun-22 8:35am    
Oh, do you know why it worked for me then? And should I mark it as not the solution?
Richard Deeming 23-Jun-22 8:42am    
There's not really enough information to know what the problem was. If it's really the FirstViewModel._navigationService field that was null, that would mean you were passing null into the constructor. But I can't see where it's actually being created.

You can guard against it by validating the constructor parameter:
public FirstViewModel(IMvxNavigationService navigationService)
{
    _navigationService = navigationService ?? throw new ArgumentNullException(nameof(navigationService));
}
ThommyaVV 23-Jun-22 8:35am    
I will at least rewrite my solution

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900