C# 使用异步任务通知属性更新
我有一个包含ListView的视图,我在其中加载了一个ObservableCollection 之后,我将从MySQL数据库中为我的集合中的每个项加载一些外部数据 我希望在异步任务中执行这些操作,以防止ui冻结 对于ListView中不可见的所有项,更新都可以正常工作。因为它们是虚拟化的 当前在ListView上可见的项目未更新。如何通知视图更新项目的属性 注意:Viewmodel通过BaseViewModel实现InotifyProperty更改C# 使用异步任务通知属性更新,c#,wpf,asynchronous,task,C#,Wpf,Asynchronous,Task,我有一个包含ListView的视图,我在其中加载了一个ObservableCollection 之后,我将从MySQL数据库中为我的集合中的每个项加载一些外部数据 我希望在异步任务中执行这些操作,以防止ui冻结 对于ListView中不可见的所有项,更新都可以正常工作。因为它们是虚拟化的 当前在ListView上可见的项目未更新。如何通知视图更新项目的属性 注意:Viewmodel通过BaseViewModel实现InotifyProperty更改 public class ProductVie
public class ProductViewModel : BaseTypes.BaseViewModel
{
public ProductViewModel()
{
}
public void GetProducts(string filter)
{
if (filter.Equals(""))
{
return;
}
Products.Clear();
Product product = new Product();
product.GetProductsByHersteller(filter);
if (product.productsList != null)
{
product.productsList.ToList().ForEach(Products.Add);
}
GetRanking();
}
private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products { get { return _Products; } private set { _Products = value; } }
async Task GetRanking()
{
await Task.Run(() => GetRank());
}
private void GetRank()
{
foreach (Product item in Products)
{
item.Rank.Get(item.Asin);
NotifyPropertyChanged(nameof(Products));
}
}
}
解决方案:
将INotifyPropertyChanged添加到排名类
ViewModel中现在的代码如下:
public void GetProducts(string filter)
{
if (filter.Equals(""))
{
return;
}
Products.Clear();
Product product = new Product();
product.GetProductsByHersteller(filter);
if (product.productsList != null)
{
product.productsList.ToList().ForEach(Products.Add);
}
GetRanking();
}
private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products { get { return _Products; } private set { _Products = value; } }
async void GetRanking()
{
await Task.Run(() => GetRank());
}
private void GetRank()
{
foreach (Product item in Products)
{
item.Rank.Get(item.Asin);
}
}
公共产品(字符串过滤器)
{
if(filter.Equals(“”)
{
返回;
}
产品;
产品=新产品();
product.GetProductsByHersteller(过滤器);
if(product.productsList!=null)
{
product.productsList.ToList().ForEach(Products.Add);
}
GetRanking();
}
私有ObservableCollection_Products=新ObservableCollection();
公共可观测集合产品{get{return}Products;}私有集合{u Products=value;}
异步void GetRanking()
{
等待任务。运行(()=>GetRank());
}
私有void GetRank()
{
foreach(产品中的产品项)
{
item.Rank.Get(item.Asin);
}
}
您的产品类应该实现INotifyPropertyChanged
然后无需在GetRank()方法中调用NotifyPropertyChanged。您现在正在从另一个线程执行
GetRank
,该线程不是UI线程。由于NotifyPropertyChanged
而导致的UI更新将因此失败。查看Dispatcher.Invoke()
和/或Dispatcher.BehinInvoke()
这将允许您更新主线程上的结果。@XAMlMAX尝试了相同的结果。用户界面不存在updated@XAMlMAX好的,BeginInvoke()可以工作,但是ui会冻结,直到工作完成。我们可以看到listview控件的xaml吗?我认为您应该在问题中添加更多信息。您尝试过的dispatcher代码,listview的XAML代码,产品类的代码..天哪,您的答案把我推向了正确的方向。我现在已经在Ranking类中添加了INotifyPropertyChanged,现在UI会一个接一个地更新每个项目。但是我很好奇为什么当我将INotifyPropertyChanged添加到Products类中时,更新不起作用,因为它保存了一个类型Ranking的属性。也许您可以添加产品类的代码来处理添加到问题。
public void GetProducts(string filter)
{
if (filter.Equals(""))
{
return;
}
Products.Clear();
Product product = new Product();
product.GetProductsByHersteller(filter);
if (product.productsList != null)
{
product.productsList.ToList().ForEach(Products.Add);
}
GetRanking();
}
private ObservableCollection<Product> _Products = new ObservableCollection<Product>();
public ObservableCollection<Product> Products { get { return _Products; } private set { _Products = value; } }
async void GetRanking()
{
await Task.Run(() => GetRank());
}
private void GetRank()
{
foreach (Product item in Products)
{
item.Rank.Get(item.Asin);
}
}