public static async Task ScrollToItem(this ScrollViewer scrollViewer, SelectorItem selectorItem) { // calculate the position object in order to know how much to scroll to var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content); var position = transform.TransformPoint(new Point(-scrollViewer.ViewportWidth / 2.0, 0)); // touch selection works without animation so the workaround is needed await Task.Delay(1); scrollViewer.ChangeView(position.X, position.Y, null); }
private static async Task ScrollIntoView( ListViewBase listViewBase, ScrollViewer scrollViewer, SelectorItem selectorItem, bool isVirtualizing, double previousXOffset, double previousYOffset, ItemPosition itemPosition = ItemPosition.Default, bool disableAnimation = false) { var transform = selectorItem.TransformToVisual((UIElement)scrollViewer.Content); var position = transform.TransformPoint(new Point(0, 0)); if (isVirtualizing) { var tcs = new TaskCompletionSource <object>(); EventHandler <ScrollViewerViewChangedEventArgs> viewChanged = (s, e) => tcs.TrySetResult(null); try { scrollViewer.ViewChanged += viewChanged; scrollViewer.ChangeView(previousXOffset, previousYOffset, null, true); await tcs.Task; } finally { scrollViewer.ViewChanged -= viewChanged; } } var listViewBaseWidth = listViewBase.ActualWidth; var selectorItemWidth = selectorItem.ActualWidth; var listViewBaseHeight = listViewBase.ActualHeight; var selectorItemHeight = selectorItem.ActualHeight; previousXOffset = scrollViewer.HorizontalOffset; previousYOffset = scrollViewer.VerticalOffset; if (itemPosition == ItemPosition.Left) { scrollViewer.ChangeView(position.X, previousYOffset, null, disableAnimation); } else if (itemPosition == ItemPosition.Top) { scrollViewer.ChangeView(previousXOffset, position.Y, null, disableAnimation); } else if (itemPosition == ItemPosition.Center) { var CentreX = (listViewBaseWidth - selectorItemWidth) / 2.0; var CentreY = (listViewBaseHeight - selectorItemHeight) / 2.0; var finalXPosition = position.X - CentreX; var finalYPosition = position.Y - CentreY; scrollViewer.ChangeView(finalXPosition, finalYPosition, null, disableAnimation); } else if (itemPosition == ItemPosition.Right) { var finalXPosition = position.X - listViewBaseWidth + selectorItemWidth; scrollViewer.ChangeView(finalXPosition, previousYOffset, null, disableAnimation); } else if (itemPosition == ItemPosition.Bottom) { var finalYPosition = position.Y - listViewBaseHeight + selectorItemHeight; scrollViewer.ChangeView(previousXOffset, finalYPosition, null, disableAnimation); } else if (itemPosition == ItemPosition.Default) { var bottomXPosition = position.X - listViewBaseWidth + selectorItemWidth; var finalXPosition = position.X; if (previousXOffset < position.X && previousXOffset > bottomXPosition) { finalXPosition = previousXOffset; } else if (Math.Abs(previousXOffset - bottomXPosition) < Math.Abs(previousXOffset - position.X)) { finalXPosition = bottomXPosition; } var rightYPosition = position.Y - listViewBaseHeight + selectorItemHeight; var finalYPosition = position.Y; if (previousYOffset < position.Y && previousYOffset > rightYPosition) { finalYPosition = previousYOffset; } else if (Math.Abs(previousYOffset - rightYPosition) < Math.Abs(previousYOffset - position.Y)) { finalYPosition = rightYPosition; } scrollViewer.ChangeView(finalXPosition, finalYPosition, null, disableAnimation); } }