Для потомков, вот мое решение прокручиваемой части вопроса.Этот код сначала обрабатывает пробел, затем, если полоса прокрутки уже находится внизу, он не обрабатывает KeyDown.Рекомендованный @ Хасан рекомендует пожары в этот момент.
internal class FlowDocumentScrollViewer2 : FlowDocumentScrollViewer
{
private static bool PageDown<T>(T listView)
where T : DependencyObject
{
var scrollViewer = GetVisualChild<ScrollViewer>(listView, null);
var scrollBar = GetVisualChild<ScrollBar>(listView,
bar => bar.Orientation == Orientation.Vertical);
var formerOffset = scrollBar.Track.Value;
scrollViewer.PageDown();
scrollBar.Track.UpdateLayout();
return formerOffset < scrollBar.Track.Value;
}
private static T GetVisualChild<T>(DependencyObject parent, Predicate<T> predicate)
where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual) VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild(v, predicate);
}
if (child != null && (predicate == null || predicate(child)))
{
break;
}
}
return child;
}
public FlowDocumentScrollViewer2()
{
PreviewKeyDown += PreviewSpaceDown;
}
private void PreviewSpaceDown(object sender, KeyEventArgs e)
{
if (e.Handled)
return;
if (e.Key == Key.Space)
{
e.Handled = PageDown(this);
}
}
}