INotifyPropertyChanged, ObservableCollection, Threads и MVVM - PullRequest
3 голосов
/ 05 января 2011

Хорошо, после вчерашнего дня я добавил новый уровень сложности. У нас все еще есть теоретический класс Model, ViewModel и View. На этот раз моя модель имеет Threading.Timer (выбранный специально для получения обратных вызовов таймера в «неправильном» потоке.

Модель имеет коллекцию ObservableCollection. Обратный вызов Timer добавляет элементы в коллекцию.

ViewModel просто передает коллекцию представлению, которое содержит список, связанный с коллекцией.

Это не работает.

Модель также предоставляет строку, которая обновляется в том же обратном вызове таймера.

Это также доступно через viewmodel и привязано к TextBox.

Это работает.

Я видел подсказки в моем поиске, что обновление коллекций не дает INotifyCollectionChanged работать должным образом. Я получаю полный взрыв, даже не исключение, просто немедленное прекращение приложения.

Итак, есть два вопроса:

Один относится к нашей вчерашней дискуссии. Я использую INotifyPropertyChanged и ObservableCollections в моей модели, потому что они - вещь, над которой работает представление. Для меня все еще имеет смысл использовать эти механизмы для уведомления моей модели представления, или чего бы то ни было, что базовая модель изменилась. Итак, как мне поступить с обновлениями, происходящими в другом потоке?

Во-вторых, что происходит, что заставляет INotifyPropertyChanged работать с привязкой? Я связываю строковое свойство с DependencyProperty с именем Text, поэтому система DependencyProperty отправляет мои изменения обратно в поток пользовательского интерфейса? Изменить: И могу ли я положиться на это, то есть делает ли это это, потому что они ожидают, что я буду говорить с ним сквозь нить, или это просто ловушка все, на что я не должен полагаться?

ListBox связан через ItemsSource = "{Binding ObsCollection}". При этом вылетает приложение. На самом деле, сначала я запустил таймер, когда создавалась Модель, что происходило, когда был задан DataContext в Window, поэтому он фактически бомбил Visual Studio ...

Спасибо

Ответы [ 2 ]

2 голосов
/ 05 января 2011

Эта проблема довольно распространена в WPF. Я думаю, что лучше всего иметь собственный подкласс ObservableCollection<>, который автоматически отправляет уведомления о событиях в поток пользовательского интерфейса.

И так как колесо уже было изобретено, я просто отправлю вас к ответу на этот вопрос: ObservableCollection и threading .

1 голос
/ 05 января 2011

Элементы управления WPF имеют привязку к потоку, это означает, что их свойства могут быть изменены только из потока пользовательского интерфейса.Следовательно, если вы обновляете значение свойства из Timer (кроме DispatcherTimer), вам придется перенести это обновление в поток пользовательского интерфейса.Это выполняется через диспетчер:

Application.Current.Dispatcher.BeginInvoke(
  DispatcherPriority.Normal,
  new Action(() => // update your control here));

Среда привязки данных не гарантирует, что обновления направляются в поток пользовательского интерфейса, поэтому, если вы обновите свою модель из другого потока, это вызовет проблемы.поэтому вам нужно использовать тот же шаблон, что и выше.Другими словами, если вы добавляете возражения в свою наблюдаемую коллекцию, это добавление должно выполняться через Диспетчер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...