#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.