internal bool HandleScrollByPage(bool up, ScrollViewer scrollHost, double viewportHeight, double top, double bottom, out double currentDelta)
{
double closeEdge = 0;
currentDelta = CalculateDelta(up, this, scrollHost, top, bottom, out closeEdge);
if (NumericExtensions.IsGreaterThan(closeEdge, viewportHeight))
{
// The item doesn't fit in the view
return false;
}
if (NumericExtensions.IsLessThanOrClose(currentDelta, viewportHeight))
{
// The item and its children fit, but don't focus because there
// might be more than fit
return false;
}
else
{
// The item is partially in the view
// Check if the header is in the view
bool headerInView = false;
FrameworkElement header = HeaderElement;
if (header != null)
{
double edge;
double delta = CalculateDelta(up, header, scrollHost, top, bottom, out edge);
if (NumericExtensions.IsLessThanOrClose(delta, viewportHeight))
{
headerInView = true;
}
}
TreeViewItem selected = null;
int count = Items.Count;
bool skip = up && ContainsSelection;
for (int index = (up ? count - 1 : 0); 0 <= index && index < count; index += (up ? -1 : 1))
{
TreeViewItem item = ItemContainerGenerator.ContainerFromIndex(index) as TreeViewItem;
if (item != null && item.IsEnabled)
{
if (skip)
{
if (item.IsSelected)
{
skip = false;
continue;
}
else if (item.ContainsSelection)
{
skip = false;
}
else
{
continue;
}
}
double delta;
if (item.HandleScrollByPage(up, scrollHost, viewportHeight, top, bottom, out delta))
{
// This item or one of its children was focused
return true;
}
else if (NumericExtensions.IsGreaterThan(delta, viewportHeight))
{
// The item does not fit
break;
}
else
{
// The item fits, but continue searching
selected = item;
}
}
}
if (selected != null)
{
if (up)
{
return selected.Focus();
}
else
{
return selected.FocusInto();
}
}
else if (headerInView)
{
// If none of the children fit but the header is in view,
// then we'll select this TreeViewItem.
return Focus();
}
}
return false;
}