Пользовательский интерфейс WPF не обновляется при изменении коллекции типов ConcurrentBag - PullRequest
2 голосов
/ 15 января 2012

У меня есть коллекция, которая ограничена сеткой данных в пользовательском интерфейсе WPF.

Мое требование таково, что мне нужно обновлять значение свойства 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);
    }
}

Ответы [ 2 ]

4 голосов
/ 15 января 2012

Не думаю, что предыдущий ответ даст решение вашей проблемы.Фактически вы вообще не обновляете коллекцию: Вы обновляете свойство всех экземпляров Stock в коллекции.Обновление коллекции означает добавление или удаление элементов в ней.Поскольку семантика отличается, возможно, связанный элемент управления не будет проверять свойства уже существующих объектов в коллекции при запуске события CollectionChanged.Это была бы разумная оптимизация.

Я бы посоветовал вам реализовать INotifyPropertyChange в вашем классе Stock и вызвать событие propertyChanged здесь (в хорошем потоке, однако, с помощью Dispatcher) в установщике свойства Price.*

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

   }
}
2 голосов
/ 15 января 2012

РЕДАКТИРОВАТЬ : Я неправильно понял ваш вопрос, касающийся обновления свойства, а не обновления коллекции.Так что, если вы действительно хотите обновить свойство 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));
...