2025-07-31 20:12:24 +08:00
|
|
|
|
using System.Windows.Markup;
|
|
|
|
|
|
|
2026-01-02 17:30:41 +08:00
|
|
|
|
namespace Melskin.Layout;
|
2025-07-31 20:12:24 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// WrapPanel 是一种布局面板,它允许子元素根据指定的方向(水平或垂直)自动换行排列。
|
|
|
|
|
|
/// 该面板提供了一种灵活的方式来控制子元素的宽度、高度以及它们之间的间距。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <remarks>
|
|
|
|
|
|
/// 通过设置 Orientation 属性,可以指定子元素的排列方向是水平还是垂直。
|
|
|
|
|
|
/// ItemWidth 和 ItemHeight 属性用于统一设置所有子元素的宽度和高度。
|
|
|
|
|
|
/// 如果不需要统一设置,则可以忽略这两个属性,每个子元素将根据其自身的内容大小进行布局。
|
|
|
|
|
|
/// VerticalSpacing 和 HorizontalSpacing 属性分别定义了垂直和水平方向上相邻子元素间的间距。
|
|
|
|
|
|
/// </remarks>
|
|
|
|
|
|
[ContentProperty(nameof(Children))]
|
|
|
|
|
|
public class WrapPanel : Panel
|
|
|
|
|
|
{
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中子元素的排列方向属性。通过设置此属性,可以控制子元素是水平排列还是垂直排列。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public static readonly DependencyProperty OrientationProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(WrapPanel), new FrameworkPropertyMetadata(Orientation.Horizontal, FrameworkPropertyMetadataOptions.AffectsMeasure));
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中子元素的排列方向属性。通过设置此属性,可以控制子元素是水平排列还是垂直排列。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public Orientation Orientation
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (Orientation)GetValue(OrientationProperty);
|
|
|
|
|
|
set => SetValue(OrientationProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中所有子元素的统一宽度属性。通过设置此属性,可以为面板中的所有子元素指定相同的宽度。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public static readonly DependencyProperty ItemWidthProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(ItemWidth), typeof(double), typeof(WrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure));
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中每个子元素的宽度。通过设置此属性,可以统一控制面板内所有子元素的宽度。如果设置了该值,则所有子元素将具有相同的宽度;若未设置(即保持默认值NaN),则每个子元素将根据其自身内容确定宽度。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public double ItemWidth
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(ItemWidthProperty);
|
|
|
|
|
|
set => SetValue(ItemWidthProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中所有子元素的统一高度属性。通过设置此属性,可以控制面板内所有子元素的高度一致。
|
|
|
|
|
|
/// 如果不需要统一设置,则可以忽略此属性,每个子元素将根据其自身的内容大小进行布局。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public static readonly DependencyProperty ItemHeightProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(ItemHeight), typeof(double), typeof(WrapPanel), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsMeasure));
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中每个子元素的高度属性。通过设置此属性,可以统一控制所有子元素的高度。
|
|
|
|
|
|
/// 如果未设置或设置为NaN,则子元素将使用其自身的高度。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public double ItemHeight
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(ItemHeightProperty);
|
|
|
|
|
|
set => SetValue(ItemHeightProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示垂直方向上相邻子元素之间的间距属性。通过设置此属性,可以控制WrapPanel中垂直排列的子元素间的距离。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public static readonly DependencyProperty VerticalSpacingProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(VerticalSpacing), typeof(double), typeof(WrapPanel), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中子元素之间的垂直间距属性。通过设置此属性,可以控制子元素在垂直方向上的间距大小。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public double VerticalSpacing
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(VerticalSpacingProperty);
|
|
|
|
|
|
set => SetValue(VerticalSpacingProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中子元素在水平方向上的间距属性。通过设置此属性,可以控制相邻子元素之间的水平间距。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public static readonly DependencyProperty HorizontalSpacingProperty =
|
|
|
|
|
|
DependencyProperty.Register(nameof(HorizontalSpacing), typeof(double), typeof(WrapPanel), new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsMeasure));
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 表示WrapPanel中子元素在水平方向上的间距属性。通过设置此属性,可以控制子元素之间的水平距离。
|
|
|
|
|
|
/// </summary>
|
2025-07-31 20:12:24 +08:00
|
|
|
|
public double HorizontalSpacing
|
|
|
|
|
|
{
|
|
|
|
|
|
get => (double)GetValue(HorizontalSpacingProperty);
|
|
|
|
|
|
set => SetValue(HorizontalSpacingProperty, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <inheritdoc />
|
2025-07-31 20:12:24 +08:00
|
|
|
|
protected override Size MeasureOverride(Size availableSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
var itemWidth = ItemWidth;
|
|
|
|
|
|
var itemHeight = ItemHeight;
|
|
|
|
|
|
var verticalSpacing = VerticalSpacing;
|
|
|
|
|
|
var horizontalSpacing = HorizontalSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
var offsetX = 0d;
|
|
|
|
|
|
var offsetY = 0d;
|
|
|
|
|
|
var maxLineLength = 0d;
|
|
|
|
|
|
var currentLineSize = 0d;
|
|
|
|
|
|
double currentLineLength;
|
|
|
|
|
|
|
|
|
|
|
|
Func<Size, double> childWidthGetter = double.IsNaN(itemWidth) ? size => size.Width : _ => itemWidth;
|
|
|
|
|
|
Func<Size, double> childHeightGetter = double.IsNaN(itemHeight) ? size => size.Height : _ => itemHeight;
|
|
|
|
|
|
|
|
|
|
|
|
var internalChildren = InternalChildren;
|
|
|
|
|
|
if (Orientation == Orientation.Horizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
availableSize.Height = double.PositiveInfinity;
|
|
|
|
|
|
for (var i = 0; i < internalChildren.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var child = internalChildren[i];
|
|
|
|
|
|
|
|
|
|
|
|
child.Measure(availableSize);
|
|
|
|
|
|
var childDesiredSize = child.DesiredSize;
|
|
|
|
|
|
var childWidth = childWidthGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
var childHeight = childHeightGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
|
|
|
|
|
|
offsetX += childWidth;
|
|
|
|
|
|
|
|
|
|
|
|
if (child.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
offsetX += horizontalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (offsetX - horizontalSpacing > availableSize.Width)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLineLength = offsetX - horizontalSpacing - childWidth - horizontalSpacing;
|
|
|
|
|
|
if (currentLineLength > maxLineLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxLineLength = currentLineLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offsetX = childWidth + horizontalSpacing;
|
|
|
|
|
|
offsetY += currentLineSize;
|
|
|
|
|
|
offsetY += verticalSpacing;
|
|
|
|
|
|
currentLineSize = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (childHeight > currentLineSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLineSize = childHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentLineLength = offsetX - horizontalSpacing;
|
|
|
|
|
|
if (currentLineLength > maxLineLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxLineLength = currentLineLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offsetY += currentLineSize;
|
|
|
|
|
|
offsetY += verticalSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
return new Size(maxLineLength, offsetY - verticalSpacing);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
availableSize.Width = double.PositiveInfinity;
|
|
|
|
|
|
for (var i = 0; i < internalChildren.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var child = internalChildren[i];
|
|
|
|
|
|
|
|
|
|
|
|
child.Measure(availableSize);
|
|
|
|
|
|
var childDesiredSize = child.DesiredSize;
|
|
|
|
|
|
var childWidth = childWidthGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
var childHeight = childHeightGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
|
|
|
|
|
|
offsetY += childHeight;
|
|
|
|
|
|
|
|
|
|
|
|
if (child.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
offsetY += verticalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (offsetY - verticalSpacing > availableSize.Height)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLineLength = offsetY - horizontalSpacing - childHeight - verticalSpacing;
|
|
|
|
|
|
if (currentLineLength > maxLineLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxLineLength = currentLineLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offsetY = childHeight + verticalSpacing;
|
|
|
|
|
|
offsetX += currentLineSize;
|
|
|
|
|
|
offsetX += horizontalSpacing;
|
|
|
|
|
|
currentLineSize = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (childWidth > currentLineSize)
|
|
|
|
|
|
currentLineSize = childWidth;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
currentLineLength = offsetY - verticalSpacing;
|
|
|
|
|
|
if (currentLineLength > maxLineLength)
|
|
|
|
|
|
{
|
|
|
|
|
|
maxLineLength = currentLineLength;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offsetX += currentLineSize;
|
|
|
|
|
|
offsetX += horizontalSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
return new Size(offsetX - horizontalSpacing, maxLineLength);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
/// <inheritdoc />
|
2025-07-31 20:12:24 +08:00
|
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
var itemWidth = ItemWidth;
|
|
|
|
|
|
var itemHeight = ItemHeight;
|
|
|
|
|
|
var verticalSpacing = VerticalSpacing;
|
|
|
|
|
|
var horizontalSpacing = HorizontalSpacing;
|
|
|
|
|
|
|
|
|
|
|
|
var tempOffset = 0d;
|
|
|
|
|
|
|
2025-08-20 12:10:13 +08:00
|
|
|
|
Func<Size, double> childWidthGetter = double.IsNaN(itemWidth) ? size => size.Width : _ => itemWidth;
|
|
|
|
|
|
Func<Size, double> childHeightGetter = double.IsNaN(itemHeight) ? size => size.Height : _ => itemHeight;
|
2025-07-31 20:12:24 +08:00
|
|
|
|
|
|
|
|
|
|
var internalChildren = InternalChildren;
|
|
|
|
|
|
var currentLineSize = 0d;
|
|
|
|
|
|
var currentLineOffsetX = 0d;
|
|
|
|
|
|
var currentLineOffsetY = 0d;
|
|
|
|
|
|
var currentLineIndexStart = 0;
|
|
|
|
|
|
if (Orientation == Orientation.Horizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < internalChildren.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var child = internalChildren[i];
|
|
|
|
|
|
var childDesiredSize = child.DesiredSize;
|
|
|
|
|
|
var childWidth = childWidthGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
var childHeight = childHeightGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
|
|
|
|
|
|
tempOffset += childWidth;
|
|
|
|
|
|
|
|
|
|
|
|
if (child.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
tempOffset += horizontalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tempOffset - horizontalSpacing > finalSize.Width)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArrangeLineHorizontal(
|
|
|
|
|
|
internalChildren,
|
|
|
|
|
|
currentLineIndexStart,
|
|
|
|
|
|
i,
|
|
|
|
|
|
currentLineOffsetX,
|
|
|
|
|
|
currentLineOffsetY,
|
|
|
|
|
|
currentLineSize,
|
|
|
|
|
|
horizontalSpacing,
|
|
|
|
|
|
childWidthGetter,
|
|
|
|
|
|
childHeightGetter);
|
|
|
|
|
|
|
|
|
|
|
|
currentLineOffsetX = 0;
|
|
|
|
|
|
currentLineOffsetY += currentLineSize;
|
|
|
|
|
|
currentLineOffsetY += verticalSpacing;
|
|
|
|
|
|
currentLineIndexStart = i;
|
|
|
|
|
|
|
|
|
|
|
|
currentLineSize = 0;
|
|
|
|
|
|
tempOffset = childWidth + horizontalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (childHeight > currentLineSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLineSize = childHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ArrangeLineHorizontal(
|
|
|
|
|
|
internalChildren,
|
|
|
|
|
|
currentLineIndexStart,
|
|
|
|
|
|
internalChildren.Count,
|
|
|
|
|
|
currentLineOffsetX,
|
|
|
|
|
|
currentLineOffsetY,
|
|
|
|
|
|
currentLineSize,
|
|
|
|
|
|
horizontalSpacing,
|
|
|
|
|
|
childWidthGetter,
|
|
|
|
|
|
childHeightGetter);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
for (var i = 0; i < internalChildren.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var child = internalChildren[i];
|
|
|
|
|
|
var childDesiredSize = child.DesiredSize;
|
|
|
|
|
|
var childWidth = childWidthGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
var childHeight = childHeightGetter.Invoke(childDesiredSize);
|
|
|
|
|
|
|
|
|
|
|
|
tempOffset += childHeight;
|
|
|
|
|
|
|
|
|
|
|
|
if (child.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
tempOffset += verticalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tempOffset - verticalSpacing > finalSize.Height)
|
|
|
|
|
|
{
|
|
|
|
|
|
ArrangeLineVertical(
|
|
|
|
|
|
internalChildren,
|
|
|
|
|
|
currentLineIndexStart,
|
|
|
|
|
|
i,
|
|
|
|
|
|
currentLineOffsetX,
|
|
|
|
|
|
currentLineOffsetY,
|
|
|
|
|
|
currentLineSize,
|
|
|
|
|
|
verticalSpacing,
|
|
|
|
|
|
childWidthGetter,
|
|
|
|
|
|
childHeightGetter);
|
|
|
|
|
|
|
|
|
|
|
|
currentLineOffsetY = 0;
|
|
|
|
|
|
currentLineOffsetX += currentLineSize;
|
|
|
|
|
|
currentLineOffsetX += horizontalSpacing;
|
|
|
|
|
|
currentLineIndexStart = i;
|
|
|
|
|
|
|
|
|
|
|
|
currentLineSize = 0;
|
|
|
|
|
|
tempOffset = childHeight + verticalSpacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (childWidth > currentLineSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
currentLineSize = childWidth;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ArrangeLineVertical(
|
|
|
|
|
|
internalChildren,
|
|
|
|
|
|
currentLineIndexStart,
|
|
|
|
|
|
internalChildren.Count,
|
|
|
|
|
|
currentLineOffsetX,
|
|
|
|
|
|
currentLineOffsetY,
|
|
|
|
|
|
currentLineSize,
|
|
|
|
|
|
verticalSpacing,
|
|
|
|
|
|
childWidthGetter,
|
|
|
|
|
|
childHeightGetter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return finalSize;
|
|
|
|
|
|
|
|
|
|
|
|
static void ArrangeLineHorizontal(
|
|
|
|
|
|
UIElementCollection children,
|
|
|
|
|
|
int childIndexStart,
|
|
|
|
|
|
int childIndexEnd,
|
|
|
|
|
|
double currentLineOffsetX,
|
|
|
|
|
|
double currentLineOffsetY,
|
|
|
|
|
|
double currentLineSize,
|
|
|
|
|
|
double spacing,
|
|
|
|
|
|
Func<Size, double> widthGetter,
|
|
|
|
|
|
Func<Size, double> heightGetter)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lineChildOffset = 0d;
|
|
|
|
|
|
for (var j = childIndexStart; j < childIndexEnd; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lineChild = children[j];
|
|
|
|
|
|
var lineChildDesiredSize = lineChild.DesiredSize;
|
|
|
|
|
|
var lineChildWidth = widthGetter.Invoke(lineChildDesiredSize);
|
2025-08-20 12:10:13 +08:00
|
|
|
|
heightGetter.Invoke(lineChildDesiredSize);
|
2025-07-31 20:12:24 +08:00
|
|
|
|
|
|
|
|
|
|
lineChild.Arrange(new Rect(currentLineOffsetX + lineChildOffset, currentLineOffsetY, lineChildWidth, currentLineSize));
|
|
|
|
|
|
|
|
|
|
|
|
lineChildOffset += lineChildWidth;
|
|
|
|
|
|
|
|
|
|
|
|
if (lineChild.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
lineChildOffset += spacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void ArrangeLineVertical(
|
|
|
|
|
|
UIElementCollection children,
|
|
|
|
|
|
int childIndexStart,
|
|
|
|
|
|
int childIndexEnd,
|
|
|
|
|
|
double currentLineOffsetX,
|
|
|
|
|
|
double currentLineOffsetY,
|
|
|
|
|
|
double currentLineSize,
|
|
|
|
|
|
double spacing,
|
|
|
|
|
|
Func<Size, double> widthGetter,
|
|
|
|
|
|
Func<Size, double> heightGetter)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lineChildOffset = 0d;
|
|
|
|
|
|
for (var j = childIndexStart; j < childIndexEnd; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
var lineChild = children[j];
|
|
|
|
|
|
var lineChildDesiredSize = lineChild.DesiredSize;
|
2025-08-20 12:10:13 +08:00
|
|
|
|
widthGetter.Invoke(lineChildDesiredSize);
|
2025-07-31 20:12:24 +08:00
|
|
|
|
var lineChildHeight = heightGetter.Invoke(lineChildDesiredSize);
|
|
|
|
|
|
|
|
|
|
|
|
lineChild.Arrange(new Rect(currentLineOffsetX, currentLineOffsetY + lineChildOffset, currentLineSize, lineChildHeight));
|
|
|
|
|
|
|
|
|
|
|
|
lineChildOffset += lineChildHeight;
|
|
|
|
|
|
|
|
|
|
|
|
if (lineChild.Visibility != Visibility.Collapsed)
|
|
|
|
|
|
{
|
|
|
|
|
|
lineChildOffset += spacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|