Silverlight BringIntoView() extension method (with OnGotFocus behavior)
It all started because I couldn't find a way to automatically scroll any element into view in Silverlight (a feature
that exists in WPF). I take that back, I could get the job done with a ListBox's ScrollIntoView(ListBoxItem item)
method, but I hardly wanted everything on my screen to be wrapped as a ListBoxItem; it feels as dirty as it sounds.
Anyways, here is the code.
/* Extension Methods */ public static class FrameworkElementExtensions { private const int ScrollPadding = 10; public static void BringIntoView(this FrameworkElement frameworkElement) { var parent = VisualTreeHelper.GetParent(frameworkElement); while(parent != null) { parent = VisualTreeHelper.GetParent(parent); var scrollViewer = parent as ScrollViewer; if(scrollViewer != null) { frameworkElement.BringIntoViewForScrollViewer(scrollViewer); break; } } } public static void BringIntoViewForScrollViewer(this FrameworkElement frameworkElement, ScrollViewer scrollViewer) { var transform = frameworkElement.TransformToVisual(scrollViewer); var positionInScrollViewer = transform.Transform(new Point(0, 0)); if (positionInScrollViewer.Y < 0 || positionInScrollViewer.Y > scrollViewer.ViewportHeight) scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + positionInScrollViewer.Y - ScrollPadding); } }
Bonus Behavior! (Behaviors?!? Here is an Introduction).
This behavior was created ensure that as a user tabs through the screen, scrolling automatically takes place.
Note: If you want to use behaviors in Silverlight, install the Blend 3 SDK and reference
Microsoft.Expression.Interactions.dll
/* Behavior class */ public class BringIntoViewOnFocusBehavior : Behavior<FrameworkElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.GotFocus += OnGotFocus; } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.GotFocus -= OnGotFocus; } private void OnGotFocus(object sender, RoutedEventArgs e1) { AssociatedObject.BringIntoView(); } }
<!-- XAML usage of custom behavior --> <UserControl xmlns:interactivity="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:behaviors="clr-namespace:YourNamespaceToBehaviors.Behaviors"> <StackPanel> <TextBox> <interactivity:Interaction.Behaviors> <behaviors:BringIntoViewOnFocusBehavior /> </interactivity:Interaction.Behaviors> </TextBox> </StackPanel> </UserControl>