private static void OnRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) { LoopPanel lp = sender as LoopPanel; DependencyObject target = e.TargetObject as DependencyObject; if (lp.BringChildrenIntoView && target != lp) { UIElement child = null; while (target != null) { if ((target is UIElement) && lp.InternalChildren.Contains(target as UIElement)) { child = target as UIElement; break; } target = VisualTreeHelper.GetParent(target); if (target == lp) { break; } } if (child != null && lp.InternalChildren.Contains(child)) { e.Handled = true; // determine if the child needs to be brought into view GeneralTransform childTransform = child.TransformToAncestor(lp); Rect childRect = childTransform.TransformBounds(new Rect(new Point(0, 0), child.RenderSize)); Rect intersection = Rect.Intersect(new Rect(new Point(0, 0), lp.RenderSize), childRect); // if the intersection is different than the child rect, it is either not visible // or only partially visible, so adjust the Offset to bring it into view if (!CalculateExtensions.AreVirtuallyEqual(childRect, intersection)) { if (!intersection.IsEmpty) { // the child is already partially visible, so just scroll it into view lp.Scroll((lp.Orientation == Orientation.Horizontal) ? (CalculateExtensions.AreVirtuallyEqual(childRect.X, intersection.X) ? childRect.Width - intersection.Width + Math.Min(0, lp.RenderSize.Width - childRect.Width) : childRect.X - intersection.X) : (CalculateExtensions.AreVirtuallyEqual(childRect.Y, intersection.Y) ? childRect.Height - intersection.Height + Math.Min(0, lp.RenderSize.Height - childRect.Height) : childRect.Y - intersection.Y)); } else { // the child is not visible at all lp.Scroll((lp.Orientation == Orientation.Horizontal) ? (CalculateExtensions.StrictlyLessThan(childRect.Right, 0.0d) ? childRect.X : childRect.Right - lp.RenderSize.Width + Math.Min(0, lp.RenderSize.Width - childRect.Width)) : (CalculateExtensions.StrictlyLessThan(childRect.Bottom, 0.0d) ? childRect.Y : childRect.Bottom - lp.RenderSize.Height + Math.Min(0, lp.RenderSize.Height - childRect.Height))); } } } } }
/// <summary> /// Provides a helper method for scrolling the panel by viewport units rather than /// adjusting the Offset property (which uses logical units) /// </summary> /// <param name="viewportUnits">The number of device independent pixels to scroll. A positive value /// scrolls the Offset forward and a negative value scrolls it backward</param> public void Scroll(double viewportUnits) { int childCount = this.InternalChildren.Count; if (childCount == 0) { return; } // determine the new Offset value required to move the specified viewport units double newOffset = this.Offset; int childIndex = this.PivotalChildIndex; bool isHorizontal = (this.Orientation == Orientation.Horizontal); bool isForwardMovement = (viewportUnits > 0); int directionalFactor = isForwardMovement ? 1 : -1; double remainingExtent = Math.Abs(viewportUnits); UIElement child = this.InternalChildren[childIndex]; double childExtent = isHorizontal ? child.DesiredSize.Width : child.DesiredSize.Height; double fractionalOffset = (this.Offset > 0) ? this.Offset - Math.Truncate(this.Offset) : 1.0d - Math.Truncate(this.Offset) + this.Offset; double childRemainingExtent = isForwardMovement ? childExtent - fractionalOffset * childExtent : fractionalOffset * childExtent; if (CalculateExtensions.LessThanOrVirtuallyEqual(childRemainingExtent, remainingExtent)) { newOffset = Math.Round(isForwardMovement ? newOffset + 1 - fractionalOffset : newOffset - fractionalOffset); remainingExtent -= childRemainingExtent; while (CalculateExtensions.StrictlyGreaterThan(remainingExtent, 0.0d)) { childIndex = isForwardMovement ? (childIndex + 1) % childCount : (childIndex == 0 ? childCount - 1 : childIndex - 1); child = this.InternalChildren[childIndex]; childExtent = isHorizontal ? child.DesiredSize.Width : child.DesiredSize.Height; if (CalculateExtensions.LessThanOrVirtuallyEqual(childExtent, remainingExtent)) { newOffset += 1.0d * directionalFactor; remainingExtent -= childExtent; } else { newOffset += remainingExtent * directionalFactor / childExtent; remainingExtent = 0.0d; } } } else { newOffset += remainingExtent * directionalFactor / childExtent; remainingExtent = 0.0d; } this.Offset = newOffset; }
public static bool AreVirtuallyEqual(Point p1, Point p2) { return(CalculateExtensions.AreVirtuallyEqual(p1.X, p2.X) && CalculateExtensions.AreVirtuallyEqual(p1.Y, p2.Y)); }
public static bool AreVirtuallyEqual(Rect r1, Rect r2) { return(CalculateExtensions.AreVirtuallyEqual(r1.TopLeft, r2.TopLeft) && CalculateExtensions.AreVirtuallyEqual(r1.BottomRight, r2.BottomRight)); }