C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト


■89804 / )  Re[11]: ReactivePropertyについて
□投稿者/ かずき (7回)-(2018/12/28(Fri) 11:56:53)
上記回答は携帯からだったので大雑把でしたが参考情報を:

ObservableCollection を使うと 10 回 Add することで 10 回 CollectionChanged イベントが発行されます。そこには差分情報だけが含まれていて WPF は差分だけを更新します。
その更新処理も描画まで行われるのではなく裏の描画するために必要な情報を更新する形になります。なので、Add を 10 回したからといって 10 回描画が走るわけではないです。

WPF の描画は保持モードとかいうキーワードで調べると色々出てくるのですが、データ更新すると即描画という感じではないです。因みに公式ドキュメントはありますが機械翻訳なので英語が読めるのでしたらそちらで見た方がいいと思います。

https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/graphics-multimedia/wpf-graphics-rendering-overview#visual-rendering-behavior

また、UI に表示されない部分の要素の追加は UI の仮想化の仕組みで、そもそも描画処理すら走りません。

https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/advanced/optimizing-performance-controls#displaying-large-data-sets

もちろん、データを一度に追加する数が増えれば増えるほど WPF が CollectionChanged の内容を見て同期をとる処理のオーバーヘッドが大きくなりますが私の環境で 10 万件のデータを追加してみて 400ms 程度の差でした。
なので、大量データを追加しない限りは同期する処理がパフォーマンス劣化につながるとは考えにくいです。

因みに List をまるごと入れ替える手法では差分ではなく全入れ替えが必ず走るので下手したら差分更新より描画まわりで遅くなることもあると思います。

ObservableCollection で大量の項目を追加したい場合は ObservableCollection を継承して AddRange メソッドを定義して、その中で CollectionChanged イベントの発行を抑止ししつつ要素を追加して最後に Reset の CollectionChanged イベントを発行することも出来ます。
下記サイトだと、ちょっと強引ですが拡張メソッドとして AddRange を追加しています。

http://artfulplace.hatenablog.com/entry/2016/12/29/133950

ということで追加するたびに描画はされないことと、全入れ替えをすると必ず全体の再描画が走るので、そこらへんを鑑みて Add で差分更新にするのか、凄く大量のデータの追加なので描画はリフレッシュするかを使い分けるのが最適だと思います。

返信 編集キー/


管理者用

- Child Tree -