昨日から続き、新しい複雑さのレイヤーを追加しました。私たちは理論的なModelクラス、ViewModelとViewを持っています。私のモデルはThreading.Timer(「間違った」スレッドのタイマーコールバックを取得するために特別に選ばれました。INotifyPropertyChanged、ObservableCollection、Threads、およびMVVM
をモデルのObservableCollectionを持っている。このタイマコールバック今回はコレクションに項目を追加します。
ViewModelには、単純に渡しますコレクションにバインドされたリストボックスが含まれているビューにコレクション。
これは動作しません。
モデルも同じタイマーコールバックで更新された文字列を公開します。
これもビューモデルを介して公開され、TextBoxにバインドされています。
これは機能します。
私のグーグルで、コレクションの更新によってINotifyCollectionChangedが期待どおりに動作しないというヒントが見られました。私は完全な爆縮を得る。例外でもなく、ただちにアプリケーションを終了させる。
ので、2つの質問があります
一つは、昨日の議論にも関します。ビューが機能するので、私はモデルでINotifyPropertyChangedとObservableCollectionsを使用しています。これらのメカニズムを使用してビューモデルに通知することや、基になるモデルが変更されたことは、今までわかってきました。だから私はどのように別のスレッドで発生した更新を扱うのですか?
第2に、INotifyPropertyChangedがバインディングで動作するのはどういうことでしょうか?文字列プロパティをTextというDependencyPropertyにバインドしています。そのため、DependencyPropertyシステムでUIスレッドに変更をマーシャリングするのですか?編集:そして私はそれに頼ることができますか?すなわち、彼らは私がそれをクロススレッドと話すことを期待しているからですか?それとも、私が頼りにすべきでないキャッチだけですか?
ListBoxはItemsSource = "{Binding ObsCollection}"によってバインドされています。これによりアプリケーションがクラッシュします。実際には、最初に私はそれが実際のVisual Studioを爆撃しまうので、ウィンドウのDataContextのは、設定されたときに起こったモデルが作成されたタイマーを開始しました...
これは素晴らしいですが、これをMVVMの観点から処理する「正しい」プロセスは何ですか?私のモデルのスレッドはコレクションを更新しています。私のモデルはDispatcherについて今知っているべきですか?それは間違っているようだ。これは、ViewModelをモデルとビューの間の正確な分離に対処するために重くすることを示唆しています。それは理にかなっていますか? – Ian
「正しい」アプローチはありません。しかし、私の個人的な好みは、ViewModelが依存する単純なインタフェースIMarshalledInvokerを作成することです。IMarshalledInvokerは、他のスレッドでアクションを呼び出すための単一のメソッドを持っています。 ViewModelをビューに結合すると、Dispatcherをカバーの下に使用するIMarshalledInvokerが作成されます。このパターンで、私はまだユニットテストをすることができます、それでもデザイナーのサポートを持つことができます、つまりそれは良いMVVMです;-) – ColinE
ああ、物事は今一緒に来ています。コミックには、私が考慮しなかった方法でお互いに関連する、異種の知識のビットがあります。まず、スレッドセーフなコレクションを作るのは難しいことです。私はそれを忘れて、私の頭の中で協会を作っていなかった...本質的に私は1つのスレッドだけを追加しています。あなたが何をするのか忘れてしまうのは面白いです。答えの要点は、複数のスレッドからの変更を1つのスレッドに振り向けることだと思います。ビューとビューモデルの間には1つのチャンネルがありますか? – Ian