Xamarin.Список форм, привязанный к ListView, иногда ненадолго отображает элементы, затем все исчезает

#c# #xamarin.forms

#c# #xamarin.forms

Вопрос:

Я следовал документации от Microsoft, чтобы создать многостраничное приложение с локальной базой данных, которое показывает короткие заметки. Однако это не соответствует MVVM. Поэтому я попытался реструктурировать код, чтобы соответствовать дизайну MVVM.

В моем файле App.xaml.cs я создаю страницу навигации на главную страницу, которая представляет собой страницу содержимого, содержащую contentView для списка заметок. Я проверил, правильно ли загружаются мои заметки, записав их в отладчик, который работает должным образом. Мой NotesView.xaml — это:

 ...
    <ContentView.BindingContext>
        <viewModel:NotesViewModel />
    </ContentView.BindingContext>
    
    <ContentView.Content>
        <StackLayout>
            <ListView Margin="{StaticResource PageMargin}"
                    ItemsSource="{Binding Notes}"
                    SelectedItem="{Binding SelectedNote}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextCell Text="{Binding Text}"
                                  Detail="{Binding Date}" />
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </ContentView.Content>
</ContentView>
  

My NotesViewModel:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using AwesomeApp.Models;

namespace AwesomeApp.ViewModels
{
    class NotesViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public NotesViewModel()
        {
            notes = new List<Note>();
            _selectedNote = new Note();
            LoadNotes();
        }

        private Note _selectedNote;
        public Note SelectedNote
        {
            get
            {
                return _selectedNote;
            }
            set
            {
                if (_selectedNote != value)
                {
                    _selectedNote = value;
                }
            }
        }

        List<Note> notes;
        public List<Note> Notes
        {
            set
            {
                if (value != notes)
                {
                    notes = value;
                    OnPropertyChanged("Notes");
                }
            }
            get
            {
                return notes;
            }
        }
        public async void LoadNotes()
        {
            notes = await App.Database.GetNotesAsync();

            foreach (var note in Notes)
            {
                System.Diagnostics.Debug.WriteLine("Notes: {0},{1},{2}", note.ID, note.Text, note.Date);
            }

        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
  

Мои заметки о модели содержат три свойства:

 public class Note : INotifyPropertyChanged
    {
        private int id;
        private string text;
        private DateTime date;
...
  

Когда я сейчас пытаюсь отобразить ListView с элементами из списка, элементы очень кратко появляются, а затем исчезают. Такое отображение элементов происходит только иногда, когда я перестраиваю приложение, когда я внес изменения в макет и сохранил их, чтобы во время отладки на телефоне Android 9.0 запускалась функция HotReload.

Ответ №1:

Не имея возможности запустить / отладить ваше приложение, я обнаружил пару ошибок, которые, как мне кажется, создают эти проблемы.

1- Измените конструктор на:

 public NotesViewModel()
{
    LoadNotes();
}
  

Если вы хотите выбрать заметку, не создавайте экземпляр новой заметки как _selectedNote = new Note(); . Выбранная заметка должна указывать на заметку в Notes списке.

2- В LoadNotes() вы должны сделать:

 Notes = await App.Database.GetNotesAsync();
  

Имейте в виду, что всегда следует использовать свойство, а не личное поле. Поскольку вы это делаете notes = ... , свойство не запускает OnPropertyChanged("Notes"); . Итак, вам либо нужно выполнить:

 notes = await App.Database.GetNotesAsync();
OnPropertyChanged("Notes");
  

или (лучше):

 Notes = await App.Database.GetNotesAsync();
  

3- Ваш класс модели не должен реализовывать INotifyPropertyChanged интерфейс, и это должно быть что-то вроде:

 public class Note {
    private int id;
    private string text;
    private DateTime date;
}
  

В любом случае у вас есть ViewModel для выполнения такого рода трюков и уведомления вашего представления об изменении данных ViewModel.

Комментарии:

1. Спасибо, ваш второй пункт исправил это! Я еще раз взгляну на понимание основ MVVM.