c# - 绑定到 ListView 的 Xamarin.Forms 列表有时会短暂显示元素,然后一切都消失了
问题描述
我按照microsoft的文档创建了一个带有本地数据库的多页应用程序,该数据库显示了简短的注释。但是,这并不遵循 MVVM。所以我尝试重构代码以符合 MVVM 设计。
在我的 App.xaml.cs 文件中,我为 MainPage 创建了一个 NavigationPage,它是一个 ContentPage,其中包含注释列表的 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>
我的笔记视图模型:
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));
}
}
}
我的模型 Notes 包含三个属性:
public class Note : INotifyPropertyChanged
{
private int id;
private string text;
private DateTime date;
...
当我现在尝试显示包含列表中项目的 ListView 时,这些项目非常短暂地出现然后消失。只有在我进行布局更改并保存它们以便在 android 9.0 手机上调试期间触发 HotReload 时重新构建应用程序时,才会显示元素。
解决方案
由于无法运行/调试您的应用程序,我发现了一些错误,我认为这些错误正在造成这些问题。
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 进行此类欺骗,并通知您的 View 有关 ViewModel 数据的更改。
推荐阅读
- r - 如何平滑R中的曲线?
- python-3.x - 如何在 Python for Video Indexer API 中将视频作为多部分/表单正文内容上传?
- c# - 部署到 Azure 服务应用后 ConfigurationBuilder.Build() 中的字符串 Null
- testing - 如何在 helper.js 中使用 .httpAuth 创建函数
- c++ - 获取数据作为 cpp 中的输入
- java - 无法在数据库中使用 BCryptPassword 保存加密密码
- php - 如何修复错误“PHP 警告:oci_execute():ORA-00932:不一致的数据类型:预期的日期为 NUMBER”?
- reactjs - 前端的用户角色/权限 - React / GraphQL / Apollo Client
- rpa - 如何使用列名在 Excel 工作表中添加两列,而不是提供单元格编号范围来定位 Uipath 中的列
- python - 通过另一列的值聚合数据框中的列?