Не отображаются привязанные данные в полях ввода Xamarin, хотя все инстансы и свойства проинициализированы

При переходе на страницу просмотра и редактирования данных (PersonDetailsPage) в полях ввода ничего не отображается :

<ContentPage 
  xmlns="http://xamarin.com/schemas/2014/forms"
  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
  x:Class="XamarinExploring.Views.PersonDetailsPage"
>
  <StackLayout>
    
    <StackLayout 
      x:Name="PersonStack"
    >
      <Label Text="Name" />
      <Entry Text="{Binding currentlyBeingEditedExistingPersonData.Name}" FontSize="Medium" />
      <Label Text="Email" />
      <Entry Text="{Binding currentlyBeingEditedExistingPersonData.Email}" FontSize="Medium" />
      <Label Text="Phone" />
      <Entry Text="{Binding currentlyBeingEditedExistingPersonData.Phone}" FontSize="Medium" />
    </StackLayout>
 
    <!-- ... -->
   
  </StackLayout>
</ContentPage>

В конструкторе PersonDetailsPage я убедился, что currentlyBeingEditedExistingPersonData проинициализировано успешно:

public partial class PersonDetailsPage : ContentPage {
  
  public PeopleListViewModel PeopleListViewModel { get; private set; }
  
  public PersonDetailsPage(PeopleListViewModel peopleListViewModel) {

    InitializeComponent();
    PeopleListViewModel = peopleListViewModel;
    BindingContext = PeopleListViewModel;

    // Всё О'K
    Console.WriteLine(PeopleListViewModel.currentlyBeingEditedExistingPersonData);
    Console.WriteLine(PeopleListViewModel.currentlyBeingEditedExistingPersonData.Name);
    Console.WriteLine(PeopleListViewModel.currentlyBeingEditedExistingPersonData.Email);
    Console.WriteLine(PeopleListViewModel.currentlyBeingEditedExistingPersonData.Phone);
  }
}

Инициализирую я currentlyBeingEditedExistingPersonData в PeopleListViewModel следующим образом:

  /* === Person viewing and editing =============================================================================== */
  private PersonViewModel _selectedPerson;
  
  /* [ Методология ] На данный момент этот класс полностью совпадает с 'PersonViewModel' , но в будущем это будет не так. */
  public CurrentlyBeingEditedExistingPersonData currentlyBeingEditedExistingPersonData;
  public class CurrentlyBeingEditedExistingPersonData : PersonViewModel {}
  
  public PersonViewModel SelectedPerson {
    
    get => _selectedPerson;
    
    set {
      
      if (_selectedPerson == value) return;

      _selectedPerson = value;
      OnPropertyChanged(nameof(SelectedPerson));

      currentlyBeingEditedExistingPersonData = new CurrentlyBeingEditedExistingPersonData {
        Name = _selectedPerson.Name,
        Email = _selectedPerson.Email,
        Phone = _selectedPerson.Phone
      };
      
      NavigationService.PushAsync(new PersonDetailsPage(this));
      
      _selectedPerson = null;
    }
  }

На этом с вопросом всё, но я бы хотел дать некоторые комментарии, показывающие ход моих мыслей. Если Вы хотите посмотреть ещё какие-нибудь фрагменты кода этого тренировочного проекта, то вот ссылка на репозиторий c проектом в текущем состоянии.

Насчёт сеттера SelectedPerson

С точки зрения логики, мне этот SelectedPerson (SelectedItem в ListView) незачем. SelectedPerson - это ссылка на один из элементов коллекции public ObservableCollection<PersonViewModel> People { get; set; }, а поскольку нам нужна возможность прерывать редактирование данных с откатом изменений, то привязывать значения полей вода напрямую к свойствам SelectedPerson неправильно. Поэтому я создал дополнительное поле currentlyBeingEditedExistingPersonData.

CurrentlyBeingEditedExistingPersonData на данный момент полностью совпадает с PersonViewModel, но в будущем это будет не так (допустим, у PersonViewModel свойства Name станет обязательным и должно будет содержать больше одного символа, а вот y CurrentlyBeingEditedExistingPersonData нет никаких обязательных свойств, потому что в процессе редактирования любое свойство может превращено в null или пустую строку.).

Вообще говоря, я бы обошелся и обычным обработчиком события Tap, но вроде как это не рекомендуется, если я использую паттерн MVVM:

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

metanit.com

А атрибута Command у ListView нет. На данный момент мне не известно никакого другого выхода из ситуации кроме как использование SelectedPerson. Но мне не нравится, что при однократном тапе на пункт списка он так и останется выбранным (из-за этого, мы не можем попасть на страницу редактирование данных одного и того же человека ещё раз, пока не побываем на странице просмотра и редактирования другого человека). Я думал, что _selectedPerson = null; решит эту проблему, но оказалось не так.

Мне и самому кажется нелогичным, что в сеттере мы затираем свойство, устанавливая его значение в null, но судя по всему, так делают (как в этом примере или этом примере).

Отсутствие скомпилированных привязок

Интегрированная среда разработки Rider подсвечивает мне, что не понимает, на что ссылается currentlyBeingEditedExistingPersonData.

введите сюда описание изображения

Погуглив, узнал о скомпилированных привязках из официальной документации, понял, что их желательно применять в целях производительность, но как сослаться на класс PeopleListViewModel.CurrentlyBeingEditedExistingPersonData - не понял и экспериментально выяснить это пока не удалось.

Примечание: мои уровни навыков на момент задавания вопроса

Привожу эту информацию затем, что Вы поняли, что потребуется объяснить на пальцах, а что можно подробно не объяснять.

  • В C# я новичок (задавал вопросы по нему и WPF несколько лет назад, но так сложились обстоятельства, что я на время должен был оставить нативную разработку и сконцентрироваться на веб-разработке)
  • В отличие от C#, в Xamarin у меня нет опыта вообще
  • Мой основной язык - TypeScript; широко использую ООП и понимаю его основы. Суммарный стаж в веб-разработке с использованием ООП - 6 лет.

Сейчас я нахожусь в ситуации, когда хотя идей создания конкретных нативных приложений с помощью Xamarin у меня хоть отбавляй, но разрыв между навыками, полученными из учебных примеров и потребными навыками для реализации моих идей огромный (это мягко сказано).


Ответы (0 шт):