Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
Hi!I have a project in Xamarin.Forms and I am using MVVM.The problem is that when I start the android emulator and the page is initializing,I get an error System.Reflection.TargetInvocation where I set the BindingContext in the view:
RegistrationPage.cs
public partial class RegistrationPage : ContentPage
 {
     public RegistrationPage(RegistrationViewModel vm)
     {

             InitializeComponent();
          this.BindingContext = vm;//here I get the error
     }
 }

When I click the error to see the details,it shows System.NullReferenceException on the values from my ViewModel which I bind in the View saying:"Object reference not set to an instance of an object".I believe that it should be normal for them to be null,but I don't understand why I get this error since the page won't even load,it will just break and show me the error.This is the rest of the code:
RegistrationPage.xaml
<pre><?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:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:l="clr-namespace:Edu.VM"
             mc:Ignorable="d"
             x:Class="Edu.Views.RegistrationPage">
    
    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="20,0">
      
        <Entry IsPassword="False" x:Name="userName" Placeholder="Name" Text="{Binding Name}" PlaceholderColor="Black" HeightRequest="40"/>
        <Entry IsPassword="False" x:Name="userEmail" Placeholder="Email" Text="{Binding Email}" PlaceholderColor="Black" HeightRequest="40"/>
        <Entry IsPassword="False" x:Name="userPhone" Placeholder="Phone" Text="{Binding Phone }" PlaceholderColor="Black" HeightRequest="40"/>
        <Entry IsPassword="True" x:Name="userPassword" Placeholder="Password" Text="{Binding Password}" PlaceholderColor="Black" HeightRequest="40"/>
        <Entry IsPassword="True" x:Name="userConfPassword" Placeholder="Confirm Password" Text="{Binding ConfPassword}" PlaceholderColor="Black" HeightRequest="40"/>
        <Button x:Name="registerUser" Command="{Binding RegisterCommand}" Text="Register"/>

    </StackLayout>
</ContentPage>

RegistrationViewModel.cs
public class RegistrationViewModel : BaseViewModel
  {
      private Users user;
      RegistrationPage page;

      public RegistrationViewModel()
      {

      }
      public RegistrationViewModel(RegistrationPage page,Users s)
      {
          user = s;
          this.page = page;

      }
  public ICommand RegisterCommand => new Command(async () => await Register());
      public async Task Register()
      {
          bool isUserAccept = await Application.Current.MainPage.DisplayAlert("Add contact", "Do you want to register?", "", "OK");
          if (isUserAccept)
          {
              await App.Data.AddUser(user);
              await page.DisplayAlert("Registration Succesful", "You have been registered" + "" + user.Name, "OK");
          }
          if (user == null)
          {
              await page.DisplayAlert("Registration went wrong", "Please complete all fields", "OK");
          }
      }


         public string Name
      {
          get { return user.Name; }
          set
          {

                  user.Name = value;
              OnPropertyChanged("Name");
          }
      }
      public string Email
      {

          get { return user.Email; }
          set
          {

                  user.Email = value;
              OnPropertyChanged("Email");
          }
      }
      public string Phone
      {
          get { return user.Phone; }
          set
          {
                  user.Phone = value;
              OnPropertyChanged("Phone");
          }
      }
      public string Password
      {
          get { return user.Password; }
          set
          {

                  user.Password = value;
              OnPropertyChanged("Password");
          }
      }
      public string ConfPassword
      {
          get { return user.ConfPassword; }
          set
          {

                  user.ConfPassword = value;
              OnPropertyChanged("ConfPassword");
          }
      }
  }


Did anyone encounter this kind of problem before?Any help would be appreciated.

What I have tried:

I have referenced the model class in the ViewModel and assigned the values of the model to the viewmodel in the constructor:
Name = user.Name;
Email = user.Email;
Password = user.Password;
ConfPassword = user.ConfPassword;
Phone = user.Phone;

I set the binding context directly into the view:
<StackLayout.BindingContext>
<l:RegistrationViewModel>
</StackLayout.BindingContext>

I deleted the TwoWay binding property for the values in the view and I also tried to check for null values in the code behind like this:
if(string.IsNullOrEmpty(name.Text)){
InitializeComponent();
}
Posted
Updated 13-May-20 1:11am

1 solution

You can't create a RegistrationPage instance without creating a RegistrationViewModel instance first.

The only way you can create a RegistrationViewModel instance without creating a RegistrationPage instance first is by calling the parameterless constructor.

The parameterless constructor doesn't initialize the user or page fields.

Anywhere that references those fields without checking for null will throw a NullReferenceException. For example, all of the user-related properties will throw the exception when you try to read them.

You either need to change your code to remove the circular dependency, or ensure that the fields are initialized before you try to access them.
 
Share this answer
 
Comments
Eliza Maria 13-May-20 7:12am    
Hi Richard!Thank you for your response.I believe you refer to what I have already tried as I did that and it still gave me the same error.I have tried this:
<StackLayout.BindingContext>
<l:RegistrationViewModel>
</StackLayout.BindingContext>
.Please let me know if i understood it wrong,but as far as I know this is how you create it.
Richard Deeming 13-May-20 12:59pm    
You're still calling the parameterless constructor of the RegistrationViewModel. The fields are still uninitialized. The properties are still going to throw a NullReferenceException because they're trying to access a member of a null reference.

Change the code to remove the circular dependency between the classes, or ensure that the fields are initialized before you try to access them.
Richard Deeming 13-May-20 13:01pm    
Think of it like this:
You have an empty parking space that's big enough to hold a car. There isn't a car in it. What colour is the car?

You're doing the same thing:
You have a field which can store a User. There isn't a User in it. What is the user's name?
Eliza Maria 13-May-20 14:00pm    
Hi Richard!I finally figured it out.I changed my code so that in my baseviewmodel I create a reference to the model class and I assign the model class to the properties.After that I created the ViewModel and from that point on it was pretty easy and the code looks cleaner.This is the tutorial I followed:http://bsubramanyamraju.blogspot.com/2018/03/xamarinforms-mvvm-sqlite-sample-for.html .Thank you for your time :).Now I know what not to do when I am working with MVVM. Best regards!

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