Windows 10 的 ListView 未将新插入的项目更新到 UWP 上的 ObservableCollection
ListView not updating on new inserted items into ObservableCollection on UWP for Windows 10
我想了解所有内容是如何连接的,我需要一些帮助。
到目前为止,我可以插入、更新、删除到 sqlite 数据库中,但是我无法使 UI 自动显示数据库中的更改,而无需我在每次对数据库进行更改时更新 ListView 上的 ItemsSource。即:
在我的App.xaml.cs
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
//Connection to the database and create the table if not there
string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
SQLiteConnection conn = new SQLiteConnection(path);
conn.CreateTable<CheckListItemModel>();
}
比起我的 MainPage.xaml,我有一个带有两个按钮和 Listview
的简单页面
<Page
x:Class="Personal_Checklist_2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Personal_Checklist_2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" >
<Button Content="Add Sample To Db" Click="Add_Sample_To_Db_Click" Margin="10,0,10,0" />
<Button Content="Clear Tasks" Click="Clear_Tasks_Click" />
</StackPanel>
<ListView Name="lvListView" Grid.Row="1" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Id}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
在 MainPage.xaml.cs 代码隐藏中,我也尽量保持简单,只需将新行添加到 table 并清除 table
using Personal_Checklist_2.DataModels;
using System.IO;
using System.Linq;
using SQLite;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.Collections.ObjectModel;
namespace Personal_Checklist_2
{
public sealed partial class MainPage : Page
{
static string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
ObservableCollection<CheckListItemModel> Tasks = new ObservableCollection<CheckListItemModel>();
public MainPage()
{
this.InitializeComponent();
using (var conn = new SQLiteConnection(path))
{
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
private void Add_Sample_To_Db_Click(object sender, RoutedEventArgs e)
{
var Task = new CheckListItemModel()
{
taskTitle = "Sample Task"
};
using (var conn = new SQLiteConnection(path))
{
conn.Insert(Task);
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
private void Clear_Tasks_Click(object sender, RoutedEventArgs e)
{
using (var conn = new SQLiteConnection(path))
{
conn.DeleteAll<CheckListItemModel>();
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
}
}
数据库 table 模型如下所示 CheckListItemModel.cs
using SQLite;
using System;
using System.ComponentModel;
namespace Personal_Checklist_2.DataModels
{
class CheckListItemModel : INotifyPropertyChanged
{
#region Private fields on DataModel
private string _taskTitle;
#endregion
#region Public properties on DataModel
[PrimaryKey, AutoIncrement]
public int taskId { get; set; }
public string taskTitle
{
get { return _taskTitle; }
set { _taskTitle = value; NotifyPropertyChanged("taskTitle"); }
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
但我觉得这样不太合适。有没有办法在每次 db.sqlite 发生一些变化时都设置 listview.ItemsSource 来实现这一目标?
您每次都在创建一个新的 ObservableCollection,而不是绑定到单个 ObservableCollection 并更改其中的项目。
因此,将 Tasks
保留为单个 ObservableCollection,并根据数据库查询结果更新其内容。
您将 ObservableCollection 转换为 List() 这就是它不更新的原因。将其更改为:
lvTasksList.ItemsSource = Tasks;
并且当您添加一个项目时,您不必再次从数据库中读取
private void Add_Sample_To_Db_Click(object sender, RoutedEventArgs e)
{
var Task = new CheckListItemModel()
{
taskTitle = "Sample Task"
};
using (var conn = new SQLiteConnection(path))
{
conn.Insert(Task);
}
Tasks.Add(Task);
}
我想了解所有内容是如何连接的,我需要一些帮助。 到目前为止,我可以插入、更新、删除到 sqlite 数据库中,但是我无法使 UI 自动显示数据库中的更改,而无需我在每次对数据库进行更改时更新 ListView 上的 ItemsSource。即:
在我的App.xaml.cs
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
//Connection to the database and create the table if not there
string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
SQLiteConnection conn = new SQLiteConnection(path);
conn.CreateTable<CheckListItemModel>();
}
比起我的 MainPage.xaml,我有一个带有两个按钮和 Listview
的简单页面<Page
x:Class="Personal_Checklist_2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Personal_Checklist_2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal" >
<Button Content="Add Sample To Db" Click="Add_Sample_To_Db_Click" Margin="10,0,10,0" />
<Button Content="Clear Tasks" Click="Clear_Tasks_Click" />
</StackPanel>
<ListView Name="lvListView" Grid.Row="1" >
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Id}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
在 MainPage.xaml.cs 代码隐藏中,我也尽量保持简单,只需将新行添加到 table 并清除 table
using Personal_Checklist_2.DataModels;
using System.IO;
using System.Linq;
using SQLite;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using System.Collections.ObjectModel;
namespace Personal_Checklist_2
{
public sealed partial class MainPage : Page
{
static string path = Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "db.sqlite");
ObservableCollection<CheckListItemModel> Tasks = new ObservableCollection<CheckListItemModel>();
public MainPage()
{
this.InitializeComponent();
using (var conn = new SQLiteConnection(path))
{
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
private void Add_Sample_To_Db_Click(object sender, RoutedEventArgs e)
{
var Task = new CheckListItemModel()
{
taskTitle = "Sample Task"
};
using (var conn = new SQLiteConnection(path))
{
conn.Insert(Task);
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
private void Clear_Tasks_Click(object sender, RoutedEventArgs e)
{
using (var conn = new SQLiteConnection(path))
{
conn.DeleteAll<CheckListItemModel>();
var query = conn.Table<CheckListItemModel>();
Tasks = new ObservableCollection<CheckListItemModel>(query.ToList());
lvTasksList.ItemsSource = Tasks.ToList(); //<<<--- If I dont do this, list is not updated
}
}
}
}
数据库 table 模型如下所示 CheckListItemModel.cs
using SQLite;
using System;
using System.ComponentModel;
namespace Personal_Checklist_2.DataModels
{
class CheckListItemModel : INotifyPropertyChanged
{
#region Private fields on DataModel
private string _taskTitle;
#endregion
#region Public properties on DataModel
[PrimaryKey, AutoIncrement]
public int taskId { get; set; }
public string taskTitle
{
get { return _taskTitle; }
set { _taskTitle = value; NotifyPropertyChanged("taskTitle"); }
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
但我觉得这样不太合适。有没有办法在每次 db.sqlite 发生一些变化时都设置 listview.ItemsSource 来实现这一目标?
您每次都在创建一个新的 ObservableCollection,而不是绑定到单个 ObservableCollection 并更改其中的项目。
因此,将 Tasks
保留为单个 ObservableCollection,并根据数据库查询结果更新其内容。
您将 ObservableCollection 转换为 List() 这就是它不更新的原因。将其更改为:
lvTasksList.ItemsSource = Tasks;
并且当您添加一个项目时,您不必再次从数据库中读取
private void Add_Sample_To_Db_Click(object sender, RoutedEventArgs e)
{
var Task = new CheckListItemModel()
{
taskTitle = "Sample Task"
};
using (var conn = new SQLiteConnection(path))
{
conn.Insert(Task);
}
Tasks.Add(Task);
}