![]() |
Модераторы: gambit, Kefir, Partizan |
![]() ![]() ![]() |
|
apor |
|
||||||||
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.5.2009 Репутация: нет Всего: нет |
Прошу помочь в решении проблемы. Суть в следующем: имеется ObservableCollection типа PriceData (поле "Код товара", поле "Цена товара"). Коллекция заполняется (или обновляется) примерно раз в секунду (в последующем может и раз в 100-200 миллисекунд). Коды товаров известны заранее - их порядка 100 тысяч и они уже содержатся в коллекции, а цена изменяется у каждого товара, который содержится в очередной порции новых данных (их приходит примерно 300 - 600 за одно обновление). В GridView при каждом приходе новых данных следует отображать две колонки: "Код товара", "Цена товара". Связываем коллекцию с помощью ItemsSourse. А проблема в следующем: в GridView следует отображать только новые пришедшие данные цены, т.е. коды статичны, а цена изменяется. Но в GridView при новой порции данных старые данные остаются, а они нам не нужны. Нужно отображать только свежие данные.
Код на VB, но примеры можно и в С#
Повторю, что загвоздка в отображении "старых" данных - они остаются в коллекции. Отображать в GridView нужно только новые пришедшие данные. Вся проблема упирается в отзывчивость UI и производительность. Можно было удалять недействительные данные методом перебора, но, если данных много, то это не решение проблемы. Возможно, я выбрал неправильный подход, но надеюсь на предложения. Я еще делал так:
В данном случае проблема со старыми данными отпадает, но UI замерзает при каждом обновлении где-то на 0,5 сек. Это сообщение отредактировал(а) apor - 20.9.2013, 10:40 |
||||||||
|
|||||||||
dzaraev |
|
||||||||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 12.1.2013 Репутация: нет Всего: 1 |
Честно говоря не совсем понятна проблема. Когда вы вызываете индексатор ObservableCollection.Item[], то коллекция генерирует событие CollectionChanged, с аргументом, у которого свойство Action установлено в значение NotifyCollectionChangedAction.Replace.
ListView на это обязательно реагирует и обновляет соответствующий визуальный элемент. Вот такой код у меня работает как и должен:
Далее, на счет подхода. Правильным является то, что вы обновляете отдельные изменившиеся элементы, а не всю коллекцию (как вы пытались делать в конце). Однако то, что вы создаёте новый объект PriceData - не оптимальное решение, т.к. ежесекундно вы создаёте огромное количество объектов, и столько же объектов становятся ненужными, следовательно помимо операции создания объектов, нагружается еще и сборщик мусора. Могу посоветовать реализовать в классе PriceData интерфейс INotifyPropertyChanged, и при обновлении цен менять состояние соответствующего объекта PriceData, а он в свою очередь будет уведомлять UI, что нужно обновиться (через событие PropertyChanged). Подробнее об этом вы можете прочитать, если погуглите паттерн MVVM для WPF. Естественно, изменять PriceData при таком варианте можно только из UI потока, т.к. иначе генерация события PropertyChanged приведёт к исключению - WPF будет ругаться, что вы полезли к UI из чужого потока. Вот такие изменения в коде нужно сделать:
Это сообщение отредактировал(а) dzaraev - 20.9.2013, 12:28 --------------------
Если вопрос решён - помечайте тему. |
||||||||||
|
|||||||||||
apor |
|
|||
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.5.2009 Репутация: нет Всего: нет |
Благодарю за ответ. Чтобы была понятна суть проблемы, я немного изменил код выше:
Первый newPrices эмулирует приход данных, второй - приход второй партии данных и т.д. Для начала жмем кнопку, затем откомментируем вторую строку newPrices и снова жмем кнопку. В итоге: напротив кодов появятся цены первого обновления данных и, якобы, второго. Мы наблюдаем как старые цены, так и новые. В этом и заключается проблема: нужно наблюдать только данные последнего обновления (125, 3). Так как цены быстро меняются, следует визуально наблюдать только свежие цены. |
|||
|
||||
dzaraev |
|
|||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 12.1.2013 Репутация: нет Всего: 1 |
Эмм, честно говоря понятней не стало ![]() ![]() --------------------
Если вопрос решён - помечайте тему. |
|||
|
||||
apor |
|
|||
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.5.2009 Репутация: нет Всего: нет |
Возможно, я не совсем правильно изложил суть вопроса, но именно такое поведение и должно выполняться. Вся проблема заключается в большом количестве элементов. Если все обновлять перед приходом следующей партии данных, то временная задержка будет существенной при высокочастотном обновлении данных. |
|||
|
||||
dzaraev |
|
||||
![]() Шустрый ![]() Профиль Группа: Участник Сообщений: 149 Регистрация: 12.1.2013 Репутация: нет Всего: 1 |
Подождите, у меня вопрос - а если цена товара с кодом 99999 например не изменилась, т.е. в новом newPrices её нет - разве её надо удалять? т.е. старая цена вообще стирается что ли?
![]() Как бы то ни было, поскольку
то тут могу посоветовать использовать виртуализацию данных или UI. Виртуализация UI позволит вам отображать и обновлять только те элементы, которые видит пользователь: http://www.zagstudio.com/blog/497#.Uj_py8BnrsN Виртуализация данных позволит вообще не держать в памяти контрола данные, которые ему не надо показывать (потому что их не видит пользователь): http://www.zagstudio.com/blog/498#.Uj_pzsBnrsN Плюс ко всему, если лень возиться с виртуализацией, попробуйте применить вариант с INotifyPropertyChanged. Поскольку WPF поддерживает асинхронное обновление отдельных свойств, вы можете даже производить обновление из другого потока. Т.е. попробуйте код:
Но не забываёте, что WPF умеет асинхронно менять только отдельные свойства, коллекции он уже обновить не сможет. Т.е. нельзя асинронно менять ObservableCollection, на который подписан ваш контрол. Это сообщение отредактировал(а) dzaraev - 23.9.2013, 10:26 --------------------
Если вопрос решён - помечайте тему. |
||||
|
|||||
apor |
|
|||
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.5.2009 Репутация: нет Всего: нет |
Задача довольно специфическая, т.к. при приходе данных производятся нужные манипуляции с ними и при новом обновлении эти данные уже устаревают, а т.к. они уже не актуальны - они больше не нужны. В любом случае, спасибо за помощь, есть над чем подумать. |
|||
|
||||
![]() ![]() ![]() |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | WPF и Silverlight | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |