Lo hice funcionar, con la ayuda de la respuesta de Kiril anterior. El contexto general de esto es que tengo formularios definidos por el usuario en mi aplicación, y este código se usa para representar los controles en un formulario.
Mi estrategia general era agregar mis controles a una cuadrícula, luego encontrar todos los elementos secundarios de ScrollViewer usando VisualTreeHelper, y agregar un manejador de eventos GotFocus a cada control.
Cuando el control se enfoca, de nuevo usando VisualTreeHelper, busco el árbol visual para encontrar el control cuyo elemento principal es la Cuadrícula que está siendo desplazada por el ScrollViewer. Luego, desplazo el ScrollViewer para hacer visible el control.
Aquí está el código (gridRender es la cuadrícula que los controles se agregan a):
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);
}
}
Nota: la clase VisualTreeHelperUtil es mi propia clase que añade algunas funciones de búsqueda útil para la clase VisualTreeHelper.
Gracias - con una pequeña modificación, que voy a publicar como respuesta, funcionó muy bien. El método TransformBounds en GeneralTransform parece ser una cosa SL3 sin embargo. –
Sé que esta es una publicación anterior, pero estoy tratando de hacer lo mismo. Estoy usando este código pero los valores Margin.Left y Margin.Top siempre son 0.El control que quiero desplazar está dentro de una cuadrícula en ScrollViewer, y el control se posiciona en la cuadrícula dándole un valor de propiedad row y rowspan. – Jeremy