2

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

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

所以我采取了 ConcurrentBag 类型的集合。更新每个项目的值后。我正在明确触发 RaisePropertyChange。但用户界面没有改变。

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);
    }
}
4

2 回答 2

4

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

我建议您在 Stock 类中实现 INotifyPropertyChange,并在 Price 属性设置器中在此处触发 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));

   }
}
于 2012-01-15T09:54:08.193 回答
2

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


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

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

你可能想做:

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

编辑

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

由于您的收藏没有实现INotifyCollectionChangednor 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));
于 2012-01-15T09:21:17.090 回答