In my windows store 8 metro style app, I have a scroll viewer for scrolling items of stack panel.
I want to scroll the scroll bar automatically when ever a selection is changed dynamically and selected item is not in visible area.
For eg : These tabs are Section tabs. When ever user clicks on skip button, the selected section is skipped and next section is selected.When user skips the last section then he jumps to the first section,but here scroll viewer does not scroll to the first tab automatically and because of that user is not able to see the selected section in the visible area.
It's easier than you probably think.
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var visual = MyRectangle.TransformToVisual(MyScrollViewer);
var point = visual.TransformPoint(new Point(0, 0));
// Windows 8.0
MyScrollViewer.ScrollToVerticalOffset(point.Y);
// Windows 8.1
MyScrollViewer.ChangeView(null, point.Y, null);
}
With this XAML
<ScrollViewer x:Name="MyScrollViewer">
<StackPanel>
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle x:Name="MyRectangle" Fill="Red" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
<Rectangle Fill="Wheat" Height="200" Width="200" Margin="10" />
</StackPanel>
</ScrollViewer>
Best of luck!
You could use ListView and ScrollIntoView method instead.
Or you could use ScrollToVerticalOffset method of ScrollViewer class but you will need size of your items to scroll correctly.
Based off Jerry's answer, the code below will change the offset of the Scroll Viewer just enough so the control is within the viewport of the ScrollViewer if it isn't already.
If the control is already completely visible, this will not scroll the scroll viewer.
var transform = control.TransformToVisual(MyScrollViewer);
var topLeft = transform.TransformPoint(new Point(0, 0));
var top = topLeft.Y;
var left = topLeft.X;
var bottom = top + control.ActualHeight;
var right = left + control.ActualWidth;
double? scrollToY = null;
if (top < 0)
{
scrollToY = top + MyScrollViewer.VerticalOffset;
}
else if (bottom > MyScrollViewer.ViewportHeight)
{
scrollToY = bottom + MyScrollViewer.VerticalOffset - MyScrollViewer.ViewportHeight;
}
double? scrollToX = null;
if (left < 0)
{
scrollToX = left + MyScrollViewer.HorizontalOffset;
}
else if (right > MyScrollViewer.ViewportWidth)
{
scrollToX = right + MyScrollViewer.HorizontalOffset - MyScrollViewer.ViewportWidth;
}
MyScrollViewer.ChangeView(scrollToX, scrollToY, null);
If you just need to scroll one axis, you can remove the code for the unneeded axis.