Я получил это на работу, с помощью ответа Кирилла выше. Общий контекст этого заключается в том, что в моем приложении есть определяемые пользователем формы, и этот код используется для визуализации элементов управления в форме.
Моя общая стратегия состояла в том, чтобы добавить свои элементы управления в 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.