#wpf #mvvm #timer #callback #collectionviewsource
#wpf #mvvm #таймер #обратный вызов #collectionviewsource
Вопрос:
У меня есть приложение WPF, разработанное для платформы MVVM, в котором конструктор ViewModel установил таймер с обратным вызовом.
Обратный вызов времени извлекает ObservableCollection и передает его в поле на виртуальной машине.
У меня есть CollectionViewSource, для свойства Source которого установлено значение ObservableCollection. Я использую CollectionViewSource, потому что хочу включить фильтрацию в коллекции.
Я обнаружил, что когда обратный вызов TimerCallback пытается передать ObservableCollection в локальное поле, свойство Source для CollectionViewSource выдает исключение {«Вызывающий поток не может получить доступ к этому объекту, поскольку он принадлежит другому потоку».}.
Я понимаю исключение, но у меня две проблемы:
- Как обойти эту проблему?
- И что более важно, почему я получаю эту проблему только при использовании CollectionViewSource? Если я удалю CollectionViewSource и сделаю ObservableCollection общедоступным свойством, я не получу такого исключения.
Любая помощь приветствуется! Спасибо, Драмми
Ответ №1:
- Используйте
DispatcherTimer
вместо класса timer, который вы используете сейчас, и убедитесь, что вы создали его в потоке пользовательского интерфейса. - Вероятно, только с
ObservableCollection
ваш пользовательский интерфейс не обновляется.
Ответ №2:
Чтобы частично ответить на ваш вопрос, любые обновления ObservableCollection, которые могут быть обнаружены элементами пользовательского интерфейса, должны быть отправлены через поток пользовательского интерфейса. Когда я хочу сделать это в MVVM, моя стратегия заключается в том, чтобы ввести SynchronizationContext в конструктор ViewModel, который я инициализирую во время запуска моего приложения. Это дает мне независимый от View framework способ отправки обновлений, которые должны быть синхронизированы с представлением.
Комментарии:
1. (psst, DispatcherSynchronizationContext)
2. SynchronizationContext.Current извлекает контекст синхронизации для текущего приложения, если доступ к нему осуществляется из потока пользовательского интерфейса; предположительно, это будет DispatcherSynchronizationContext в WPF.