上記のキリルの答えの助けを借りて、これを機能させました。これの一般的なコンテキストは、アプリケーションにユーザー定義可能なフォームがあり、このコードはフォーム上のコントロールをレンダリングするために使用されるということです。
私の一般的な戦略は、コントロールを Grid に追加し、次に VisualTreeHelper を使用して ScrollViewer のすべての子を見つけ、各コントロールに GotFocus イベント ハンドラーを追加することでした。
コントロールがフォーカスを取得したら、再び VisualTreeHelper を使用してビジュアル ツリーを検索し、ScrollViewer によってスクロールされている Grid を親とするコントロールを見つけます。次に、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 クラスに追加する独自のクラスです。