この質問はすでにここで尋ねられていることは知っていますが、答えはありません。もう一度質問しますが、この問題を解決できるかどうかを確認するために、これに関する独自の調査を提供します。
問題
データバインドされた ListBox があります。新しい要素をデータ ソースに追加するときに、ビューポート (表示されている要素) を保持したい。このようにして、ビューを変更せずに新しい要素を追加できます。
現在の WP の動作は、スクロール位置を保持することです (ScrollViewer.VerticalOffset は一定です)。このように、新しい要素を追加すると、それらはすべてダウンします。
可能な解決策
私はこれについて多くのことを掘り下げてきましたが、いくつかの手がかりがあります。
リストが一番上にない場合、データ ソースの更新を無効にします。このようにして、ビューポートを変更せずに新しいアイテムを追加できます。問題: ユーザーが再び一番上に移動すると、すべての新しい要素が突然リストの一番上に表示され、連続性が失われます。
ScrollIntoView
現在表示されているアイテムを取得し、すべての新しい要素が追加されたときにそれを復元します。最初はこれが最善の選択肢に思えるかもしれませんが、そうではないことを信じてください。まず、現在表示されているアイテムを取得するのは簡単ではありません。LinqToVisualTreeを使用して実行できますが、正確ではないため (推測するしかありません。ビューポート バッファーのサイズは一定ではありません)、ユーザーが以前にいた正確な位置を復元しません。 . そして、この解決策は「ジャンプ」します。ユーザーの視点からは 2 つのスクロール イベントが発生し、これは良くありません。垂直方向のオフセットを補正するために、追加されるすべての要素の垂直方向のサイズを計算します。これは良い解決策のように思えます (私は現在調査中です) が、その「ジャンピー」効果もあるのではないかと心配しています。
PrepareContainerForItemOverride
Listboxのメソッドをオーバーライドして実行します。基本メソッドが既にコンテナーを準備したら、その高さを取得してカウンターに追加します。次に、ロードが終了したら、取得した垂直オフセットまでスクロールします。継続的に行うことは不可能です(ScrollToVerticalOffset
メソッドを呼び出すことしかできず、すぐにスクロールすることはできません)ので、これが決定的な解決策になるとは思いません。
私の推測では、これを達成するには、Listbox の定義を深く掘り下げる必要があります。どこかで、Listbox は ItemsSource プロパティの CollectionChanged イベントを管理します。そこで、リストはバッファを再作成することを決定します (リストボックス バッファの詳細はこちら)。それらは ScrollViewer (定数) の VerticalOffset プロパティに依存するため、ビューポートが変更されます。バッファを再作成しないようにリストボックスを変更する必要があります。問題は、これを行う方法がわからないことです。
これについて何か考えはありますか?
ありがとう!
編集: ObservableCollection を使用してアイテムを追加していることは明らかです。ItemsSource プロパティ自体は更新していません。