Eliza Maria Ответов: 1

Ошибка system.refection.targetinvocation при установке контекста привязки в поле зрения


Привет!У меня есть проект в Xamarin.Формы, и я использую MVVM.Проблема в том,что когда я запускаю эмулятор android и страница инициализируется, я получаю систему ошибок.Отражение.TargetInvocation, где я установить восстановления команда bindingcontext в представлении:
RegistrationPage.в CS
public partial class RegistrationPage : ContentPage
 {
     public RegistrationPage(RegistrationViewModel vm)
     {

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

Когда я нажимаю на ошибку,чтобы увидеть подробности, она показывает System.NullReferenceException на значениях из моей ViewModel, которые я связываю в представлении, говоря:"ссылка на объект не установлена на экземпляр объекта".Я считаю,что это должно быть нормально для них,чтобы быть нулевым, но я не понимаю, почему я получаю эту ошибку, так как страница даже не будет загружаться, она просто сломается и покажет мне ошибку.Это остальная часть кода:
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");
          }
      }
  }


Кто-нибудь сталкивался с подобной проблемой раньше?Любая помощь будет оценена по достоинству.

Что я уже пробовал:

Я сослался на класс модели в ViewModel и присвоил значения модели viewmodel в конструкторе:
Name = user.Name;
Email = user.Email;
Password = user.Password;
ConfPassword = user.ConfPassword;
Phone = user.Phone;

Я устанавливаю контекст привязки непосредственно в представлении:
<StackLayout.BindingContext>
<l:RegistrationViewModel>
</StackLayout.BindingContext>

Я удалил свойство привязки TwoWay для значений в представлении, а также попытался проверить наличие нулевых значений в коде, например:
if(string.IsNullOrEmpty(name.Text)){
InitializeComponent();
}

1 Ответов

Рейтинг:
9

Richard Deeming

Вы не можете создать RegistrationPage экземпляр без создания RegistrationViewModel первой инстанции.

Единственный способ, которым вы можете создать RegistrationViewModel экземпляр без создания RegistrationPage первый экземпляр-это вызов конструктора без параметров.

Конструктор без параметров не инициализирует user или page поля.

В любом месте, которое ссылается на эти поля без проверки на наличие null будет бросать а NullReferenceException Например, все свойства, связанные с пользователем, будут вызывать исключение при попытке их чтения.

Вам нужно либо изменить свой код, чтобы удалить циклическую зависимость, либо убедиться, что поля инициализированы, прежде чем пытаться получить к ним доступ.


Eliza Maria

Привет, Ричард!Спасибо за ваш ответ.Я полагаю, что вы ссылаетесь на то, что я уже пробовал, поскольку я сделал это, и это все еще дало мне ту же ошибку.Я уже пробовал это сделать:

<StackLayout.BindingContext>
<l:RegistrationViewModel>
</StackLayout.BindingContext>
Пожалуйста,дайте мне знать, если я понял это неправильно, но, насколько я знаю, именно так вы его создаете.

Richard Deeming

Вы все еще вызываете беспараметрический конструктор объекта RegistrationViewModel Поля все еще неинициализированы. Свойства все еще собираются выбросить NullReferenceException потому что они пытаются получить доступ к члену а null ссылка.

Измените код, чтобы удалить циклическую зависимость между классами, или убедитесь, что поля инициализированы, прежде чем пытаться получить к ним доступ.

Richard Deeming

Подумайте об этом так:
У вас есть свободное парковочное место, достаточно большое, чтобы вместить машину. В нем нет машины. Какого цвета машина?

Ты делаешь то же самое:
У вас есть поле, которое может хранить a User- А вот и нет. User в этом. Каково имя пользователя?

Eliza Maria

Привет, Ричард!Наконец-то я это понял.Я изменил свой код так, что в моей baseviewmodel я создаю ссылку на класс модели и назначаю класс модели свойствам.После этого я создал ViewModel, и с этого момента это было довольно легко, и код выглядит чище.Это учебник, который я followed:http://bsubramanyamraju.blogspot.com/2018/03/xamarinforms-mvvm-sqlite-sample-for.html .Спасибо за ваше время :).теперь я знаю, чего не следует делать, когда я работаю с MVVM. С наилучшими пожеланиями!