Заключение в кавычки Страница Форм в руководстве HTML:
Кнопки создали с функцией элемента КНОПКИ точно так же, как кнопки, созданные с ВХОДНЫМ элементом, но они предлагают более богатые возможности рендеринга: элемент КНОПКИ может иметь содержание. Например, элемент КНОПКИ, который содержит изображение, функционирует как и может напомнить ВХОДНОЙ элемент, тип которого установлен "отобразить", но тип элемента КНОПКИ позволяет содержание.
Я тестировал это с помощью 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. У меня это сработало. Попробуйте и расскажите, как это работает для вас.
Я заставил это работать с помощью ответа Кирилла выше. Общий контекст этого состоит в том, что в моем приложении есть определяемые пользователем формы, и этот код используется для отрисовки элементов управления в форме.
Моя общая стратегия заключалась в том, чтобы добавить мои элементы управления в сетку, а затем найти всех дочерних элементов. 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);
}
}
Примечание:
Просто небольшое улучшение. Кстати, это еще нужно сделать для 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
}