スクロールしてマウスで上部の表示されるコンテナを選択すると、非仮想化の場合と同じ効果が得られます。ItemsControl
(ScrollViewer.CanContentScroll="False"
)は仮想化の場合と同じです。これはコードでも行うことができます。
CanContentScroll
がfalseに設定されていると、仮想化がオフになり、すべてのコンテナが常に生成されます。上部の可視コンテナを取得するには、ScrollViewer
のVerticalOffset
に達するまで、上部からコンテナを反復することができます。私たちが入手したら、単にBringIntoView
と呼ぶことができます。仮想化が使用されていたのと同じように、一番上にうまく整列します。であなたはPageDown
を呼び出したい場合にのみ、この効果を達成するために、イベントハンドラ
private void listBox_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
ItemsControl itemsControl = sender as ItemsControl;
ScrollViewer scrollViewer = e.OriginalSource as ScrollViewer;
FrameworkElement lastElement = null;
foreach (object obj in itemsControl.Items)
{
FrameworkElement element = itemsControl.ItemContainerGenerator.ContainerFromItem(obj) as FrameworkElement;
double offset = element.TransformToAncestor(scrollViewer).Transform(new Point(0, 0)).Y + scrollViewer.VerticalOffset;
if (offset > e.VerticalOffset)
{
if (lastElement != null)
lastElement.BringIntoView();
break;
}
lastElement = element;
}
}
で上部可視コンテナに
例
<ListBox ItemsSource="{Binding MyCollection}"
ScrollViewer.CanContentScroll="False"
ScrollViewer.ScrollChanged="listBox_ScrollChanged" >
コールBringIntoView
、たとえば、ボタンをクリックすると、拡張機能を作成できます。 thod for ListBox
はLogicalPageDown
と呼ばれます。
listBox.LogicalPageDown();
ListBoxExtensions
public static class ListBoxExtensions
{
public static void LogicalPageDown(this ListBox listBox)
{
ScrollViewer scrollViewer = VisualTreeHelpers.GetVisualChild<ScrollViewer>(listBox);
ScrollChangedEventHandler scrollChangedHandler = null;
scrollChangedHandler = (object sender2, ScrollChangedEventArgs e2) =>
{
scrollViewer.ScrollChanged -= scrollChangedHandler;
FrameworkElement lastElement = null;
foreach (object obj in listBox.Items)
{
FrameworkElement element = listBox.ItemContainerGenerator.ContainerFromItem(obj) as FrameworkElement;
double offset = element.TransformToAncestor(scrollViewer).Transform(new Point(0, 0)).Y + scrollViewer.VerticalOffset;
if (offset > scrollViewer.VerticalOffset)
{
if (lastElement != null)
lastElement.BringIntoView();
break;
}
lastElement = element;
}
};
scrollViewer.ScrollChanged += scrollChangedHandler;
scrollViewer.PageDown();
}
}
私はあなたがすでにScrollViewer
を得たあなたの質問に気づいたが、他の誰がこの質問
public static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
@ Zmaster:コンテナの相対的な位置を見つけるときに、「マージン」などが関与することを忘れています。それに応じて私の答えを更新しました –
私はScrollToOffset()を使って、すべてのアイテムの高さが同じであるという前提でターゲットオフセットを計算しました(これは私の場合です)。アイテムを反復するよりも効率的です。一方、あなたのソリューションは異なるアイテムの高さでも動作するので、私はそれを答えとして受け入れました。 – Zmaster