protected virtual void ArrangeCore(Rect finalRect) { if (IsVisible) { var useLayoutRounding = UseLayoutRounding; var scale = LayoutHelper.GetLayoutScale(this); var margin = Margin; var originX = finalRect.X + margin.Left; var originY = finalRect.Y + margin.Top; // Margin has to be treated separately because the layout rounding function is not linear // f(a + b) != f(a) + f(b) // If the margin isn't pre-rounded some sizes will be offset by 1 pixel in certain scales. if (useLayoutRounding) { margin = LayoutHelper.RoundLayoutThickness(margin, scale, scale); } var availableSizeMinusMargins = new Size( Math.Max(0, finalRect.Width - margin.Left - margin.Right), Math.Max(0, finalRect.Height - margin.Top - margin.Bottom)); var horizontalAlignment = HorizontalAlignment; var verticalAlignment = VerticalAlignment; var size = availableSizeMinusMargins; if (horizontalAlignment != HorizontalAlignment.Stretch) { size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - margin.Left - margin.Right)); } if (verticalAlignment != VerticalAlignment.Stretch) { size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - margin.Top - margin.Bottom)); } size = LayoutHelper.ApplyLayoutConstraints(this, size); if (useLayoutRounding) { size = LayoutHelper.RoundLayoutSizeUp(size, scale, scale); availableSizeMinusMargins = LayoutHelper.RoundLayoutSizeUp(availableSizeMinusMargins, scale, scale); } size = ArrangeOverride(size).Constrain(size); switch (horizontalAlignment) { case HorizontalAlignment.Center: case HorizontalAlignment.Stretch: originX += (availableSizeMinusMargins.Width - size.Width) / 2; break; case HorizontalAlignment.Right: originX += availableSizeMinusMargins.Width - size.Width; break; } switch (verticalAlignment) { case VerticalAlignment.Center: case VerticalAlignment.Stretch: originY += (availableSizeMinusMargins.Height - size.Height) / 2; break; case VerticalAlignment.Bottom: originY += availableSizeMinusMargins.Height - size.Height; break; } if (useLayoutRounding) { originX = LayoutHelper.RoundLayoutValue(originX, scale); originY = LayoutHelper.RoundLayoutValue(originY, scale); } Bounds = new Rect(originX, originY, size.Width, size.Height); } }
protected virtual Size MeasureCore(Size availableSize) { if (IsVisible) { var margin = Margin; var useLayoutRounding = UseLayoutRounding; var scale = 1.0; if (useLayoutRounding) { scale = LayoutHelper.GetLayoutScale(this); margin = LayoutHelper.RoundLayoutThickness(margin, scale, scale); } ApplyStyling(); ApplyTemplate(); var constrained = LayoutHelper.ApplyLayoutConstraints( this, availableSize.Deflate(margin)); var measured = MeasureOverride(constrained); var width = measured.Width; var height = measured.Height; { double widthCache = Width; if (!double.IsNaN(widthCache)) { width = widthCache; } } width = Math.Min(width, MaxWidth); width = Math.Max(width, MinWidth); { double heightCache = Height; if (!double.IsNaN(heightCache)) { height = heightCache; } } height = Math.Min(height, MaxHeight); height = Math.Max(height, MinHeight); if (useLayoutRounding) { (width, height) = LayoutHelper.RoundLayoutSizeUp(new Size(width, height), scale, scale); } width = Math.Min(width, availableSize.Width); height = Math.Min(height, availableSize.Height); return(NonNegative(new Size(width, height).Inflate(margin))); } else { return(new Size()); } }