WPF UI未在更改ConcurrentBag类型集合时更新

本文关键字:类型 集合 更新 ConcurrentBag UI WPF | 更新日期: 2023-09-27 18:20:25

我有一个集合,它绑定到WPF UI中的数据网格。

我的要求是,我必须为集合中的每个项目每秒更新属性的值10次。

所以我采用了ConcurrentBag类型的集合。更新每个项目的值之后。我正在显式启动RaisePropertyChange。但是UI并没有改变。

private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    if (stockCollection != null)
    {
        stockCollection.ToList().ForEach((s) => s.Price = DateTime.Now.Millisecond);
        Action raiseStockCollectionProperty = new Action(() => RaisePropertyChangedEvent("StockCollection"));
        Dispatcher.BeginInvoke(raiseStockCollectionProperty);
    }
}

WPF UI未在更改ConcurrentBag类型集合时更新

我认为前面的答案不会为您的问题提供解决方案。事实上,您根本没有更新集合:您正在更新集合中所有Stock实例的属性。更新集合意味着添加或删除其中的项。由于语义不同,当您触发CollectionChanged事件时,绑定控件可能不会检查集合中现有对象的属性。这将是一个合理的优化。

我建议您在Stock类中实现INotifyPropertyChange,并在Price属性setter中在此处激发propertyChanged事件(不过,在好的线程上,使用Dispatcher)。

private DateTime _price;
public DateTime Price
{
   get
   {
     return _price;
   }
   set
   {
     if(_price!=value)
     {
       _price = value;
       RaisePropertyChanged("Price");
     }
   }
}
protected void RaisePropertyChanged(string property)
{
   var propertyChanged = PropertyChanged;
   if(propertyChanged!=null)
   {
     propertyChanged(this,new PropertyChangedEventArgs(property));
   }
}

EDIT:我误解了您的问题,实际上是关于属性更新,而不是集合更新。因此,如果您真的想更新集合中所有项的Price属性,那么下面示例中的Where子句当然对您没有帮助。


你实际上并没有修改你的收藏;)

stockCollection.ToList().ForEach((s) => s.Price = DateTime.Now.Millisecond);

你可能想做:

stockCollection = new ConcurrentBag(stockCollection.Where(...));

编辑

意思是,我每次都需要创建一个新的集合对象?

由于您的集合既没有实现INotifyCollectionChanged,也没有实现INotifyPropertyChanged,所以是的。如果可能的话,我建议使用ObservableCollection而不是您当前的收藏类型。ObservableCollection能够通知项目属性的更新,并在添加/删除项目时引发事件。

ObservableCollection<YourType> myCollection = new ObservableCollection<YourType>();
...
public ObservableCollection<YourType> MyCollection
{
    get
    {
        return this.myCollection;
    }
    set
    {
        if (value != this.myCollection)
        {
            this.myCollection = value;
            this.RaisePropertyChanged("MyCollection");
        }
    }
}
...
// Following lines of code will update the UI because of INotifyCollectionChanged implementation
this.MyCollection.Remove(...)
this.MyCollection.Add(...)
// Following line of code also updates the UI cause of RaisePropertyChanged
this.MyCollection = new ObservableCollection<YourType>(this.MyCollection.Where(z => z.Price == 45));