Как я могу заставить Silverlight ScrollViewer прокручиваться, чтобы показать дочерний элемент управления с фокусом?

StackOverflow https://stackoverflow.com/questions/1225318

  •  22-07-2019
  •  | 
  •  

Вопрос

У меня есть ScrollViewer, который содержит сетку с несколькими элементами управления в ней.Пользователь может переходить по элементам управления, но в конечном итоге он переходит к элементу управления, которого нет в поле зрения, поэтому ему приходится вручную прокручивать, чтобы элемент управления снова стал видимым.

Есть ли какой-нибудь способ заставить ScrollViewer автоматически прокручиваться, чтобы сфокусированный элемент управления всегда был виден?В противном случае, есть ли какой-либо способ заставить это работать, за исключением прослушивания события GotFocus для каждого элемента управления, а затем прокрутки ScrollViewer, чтобы сделать элемент управления видимым?

В настоящее время я использую Silverlight 2.

Это было полезно?

Решение

Я протестировал это с помощью Silverlight 3. Я не уверен насчет SL2.

Это мой 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>

И это код позади:

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);
}

Я нажал кнопку № 1 и вкладку, пока не дошел до кнопки № 20. Это сработало для меня. Попробуйте и дайте мне знать, как это работает для вас.

Другие советы

Инструментарий silverlight содержит метод "scrollIntoView".

Добавьте ссылку на Систему.Windows.Элементы управления.Инструментарий.dll и вы должны уметь использовать приведенный ниже код.

scrollViewer.ScrollIntoView(control);

Просто небольшое улучшение. Кстати, сделать это для Silverlight 4 еще нужно. Вместо GotFocus для каждого элемента управления вы можете обрабатывать GotFocus самого прокрутки и реализовывать его только один раз.

 private void _ScrollViewer_GotFocus(object sender, RoutedEventArgs e)
        {
            FrameworkElement element = e.OriginalSource as FrameworkElement;

            if (element != null)
            {
                ScrollViewer scrollViewer = sender as ScrollViewer;
                scrollViewer.ScrollToVerticalOffset(GetVerticalOffset(element, scrollViewer));
            }

        }

        private double GetVerticalOffset(FrameworkElement child, ScrollViewer scrollViewer)
        {
            // Ensure the control is scrolled into view in the ScrollViewer. 
            GeneralTransform focusedVisualTransform = child.TransformToVisual(scrollViewer);
            Point topLeft = focusedVisualTransform.Transform(new Point(child.Margin.Left, child.Margin.Top));
            Rect rectangle = new Rect(topLeft, child.RenderSize);
            double newOffset = scrollViewer.VerticalOffset + (rectangle.Bottom - scrollViewer.ViewportHeight);
            return newOffset < 0 ? 0 : newOffset; // no use returning negative offset
        }

Я получил это на работу, с помощью ответа Кирилла выше. Общий контекст этого заключается в том, что в моем приложении есть определяемые пользователем формы, и этот код используется для визуализации элементов управления в форме.

Моя общая стратегия состояла в том, чтобы добавить свои элементы управления в Grid, затем найти всех дочерних элементов ScrollViewer с помощью VisualTreeHelper и добавить обработчик событий GotFocus для каждого элемента управления.

Когда элемент управления получает фокус, снова используя VisualTreeHelper, я ищу в визуальном дереве элемент управления, чьим родителем является Grid, который прокручивается ScrollViewer. Затем я прокручиваю ScrollViewer, чтобы сделать элемент управления видимым.

Вот код (gridRender - это таблица, в которую добавляются элементы управления):

private void AfterFormRendered()
{
    var controls = VisualTreeHelperUtil.FindChildren<Control>(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);
    }
}

Примечание. Класс VisualTreeHelperUtil - это мой собственный класс, который добавляет некоторые полезные функции поиска в класс VisualTreeHelper.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top