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

后端 未结 4 1972
时光取名叫无心
时光取名叫无心 2021-02-05 16:30

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 th

4条回答
  •  深忆病人
    2021-02-05 16:53

    I got this to work, with help of Kiril's answer above. The general context of this is that I have user-defineable forms in my application, and this code is used for rendering the controls on a form.

    My general strategy was to add my controls to a Grid, then find all the children of the ScrollViewer using VisualTreeHelper, and add a GotFocus event handler to each control.

    When the control gets focus, again using VisualTreeHelper, I search up the visual tree to find the control whose parent is the Grid that is being scrolled by the ScrollViewer. Then I scroll the ScrollViewer to make the control visible.

    Here's the code (gridRender is the Grid that the controls are added to):

    private void AfterFormRendered()
    {
        var controls = VisualTreeHelperUtil.FindChildren(gridRender);
        foreach (var ctrl in controls)
        {
            ctrl.GotFocus += CtrlGotFocus;
        }
    }
    
    private void CtrlGotFocus(object sender, RoutedEventArgs e)
    {
        var ctrl = sender as Control;
        var gridChildControl = VisualTreeHelperUtil.FindParentWithParent(ctrl, gridRender) as FrameworkElement;
    
        if (gridChildControl != null)
        {
            // Ensure the control is scrolled into view in the ScrollViewer.
            GeneralTransform focusedVisualTransform = gridChildControl.TransformToVisual(scrollViewer);
            Point topLeft = focusedVisualTransform.Transform(new Point(gridChildControl.Margin.Left, gridChildControl.Margin.Top));
            Rect rectangle = new Rect(topLeft, gridChildControl.RenderSize);
            double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);    
    
            scrollViewer.ScrollToVerticalOffset(newOffset);
        }
    }
    

    Note: the VisualTreeHelperUtil class is my own class that adds some useful searching functionality to the VisualTreeHelper class.

提交回复
热议问题