How to make the Silverlight ScrollViewer scroll to show a child control with focus

scrollviewersilverlight

I have a ScrollViewer which contains a Grid with multiple controls in it. The user can tab through the controls, but eventually they tab to a control that isn't in view – so they have to manully scroll to make the control visible again.

Is there any way to make the ScrollViewer scroll automatically so that the focussed control is always visible. Failing that, is there any way I can make this work, short of listening to a GotFocus event on every control and then scrolling the ScrollViewer to make the control visible?

At present I'm using Silverlight 2.

Best Answer

I tested this using Silverlight 3. I am not sure about SL2.

This is my XAML:

<ScrollViewer Height="200" Width="200" KeyUp="ScrollViewer_KeyUp">
    <StackPanel>
        <Button Content="1" Height="20" />
        <Button Content="2" Height="20" />
        <Button Content="3" Height="20" />
        <Button Content="4" Height="20" />
        <Button Content="5" Height="20" />
        <Button Content="6" Height="20" />
        <Button Content="7" Height="20" />
        <Button Content="8" Height="20" />
        <Button Content="9" Height="20" />
    <Button Content="10" Height="20" />
        <Button Content="11" Height="20" />
        <Button Content="12" Height="20" />
        <Button Content="13" Height="20" />
        <Button Content="14" Height="20" />
        <Button Content="15" Height="20" />
        <Button Content="16" Height="20" />
        <Button Content="17" Height="20" />
        <Button Content="18" Height="20" />
        <Button Content="19" Height="20" />
        <Button Content="20" Height="20" />
    </StackPanel>
</ScrollViewer>

And this is the code-behind:

private void ScrollViewer_KeyUp(object sender, KeyEventArgs e)
{
    ScrollViewer scrollViewer = sender as ScrollViewer;
    FrameworkElement focusedElement = FocusManager.GetFocusedElement() as FrameworkElement;
    GeneralTransform focusedVisualTransform = focusedElement.TransformToVisual(scrollViewer);
    Rect rectangle = focusedVisualTransform.TransformBounds(new Rect(new Point(focusedElement.Margin.Left, focusedElement.Margin.Top), focusedElement.RenderSize));
    double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);
    scrollViewer.ScrollToVerticalOffset(newOffset);
}

What I did was to click on Button #1 and tab until I get to Button #20. It worked for me. Give it a try and let me know how it works for you.

Related Topic