私はリスト内の一番上の項目にスクロールするScrollIntoView
を使用して、」(デフォルトでは常に一番下のものにスクロールしていますが、一部の指定された場合には、私はこれに他の方法が必要です)WPFのscrollIntoView奇妙な行動
だから、最初のアイテムがリストに追加され、次にScrollIntoView(Items[0])
が呼び出されます。 ScrollIntoViewはDispatcher.BeginInvoke
の内部で呼び出されているため、UIスレッド内にあります。
一般的な考え方は、項目の「短い」説明で初期リストを見てから、そのうちの1つを選択し、「短い」部分も含むすべての情報を見るということです。
すなわち:
1)
2)
私はケース1の要素1をクリックしてるときに、私が期待してい写真2を参照してください。しかし時々私は参照してください
たとえば、カーソルがリストボックスにとどまっていると、ビューが常に正しく更新されていることがわかりました。私は "AddItem"と "ScrollTop"メソッドの呼び出しスタックをチェックしました。それらは正しい順序であり、 "ScrollTop"は常に適切に呼び出されます。
他のすべてのケース(アイテム2またはアイテム0をピックアップしているとき)では、「ScrollTop」がうまく機能します。
だから私はWPFの最適化のようなものだと思います。 1)の項目1の情報はケース2の場合と同じ場所にあるためです。 WPFは毎回ビューを更新するわけではありません。
リストボックスをスクロールした後に毎回更新する方法はありますか?
私はUpdateLayout()
で試しました。それは助けになりませんでした。
UPDATE(コード例): メインスレッドコード:
UIManager.AddListItem(item1);
UIManager.AddListItem(item2);
UIManager.AddListItem(item3);
UIManager.ScrollToTop();
UIManagerの実装:
public void AddListItem(ListItem item)
{
ExecuteUI(() =>
{
MyList.AddItem(item);
});
}
public void ScrollToTop()
{
ExecuteUI(() =>
{
MyList.ScrollToTop();
});
}
MyListModel実装:
public void AddItem(ListItem item)
{
lock (linesLock)
{
if (Lines == null)
Lines = new ObservableCollection<ItemModel>();
ItemModel line = new ItemModel(item);
Lines.Add(line); //When line added it automatically scrolls to it
// via ((INotifyCollectionChanged)ListLines.Items).CollectionChanged += LinesChanged;
}
}
public void ScrollToTop()
{
if (Lines.Count == 0 || ScrollEvent == null)
return;
ScrollEvent(this, new ScrollEventArgs(Lines[0]));
// via Model.ScrollEvent += ScrollEvent;
}
モデルXAMLコード:
// ListLines is a ListBox
private void LinesChanged(object sender, NotifyCollectionChangedEventArgs e)
{
ListLines.ScrollIntoView(e.NewItems[0]);
}
private void ScrollEvent(object sender, ScrollEventArgs e)
{
ListLines.ScrollIntoView(e.Item);
}
残念ながら、これは私が説明したのと同じ結果をもたらします。コード例を追加しました。 – Ksice