您没有说如何定位控件的子元素,但子元素是相对于控件的,因此您需要控件缩小其空白左侧和顶部区域,然后移动控件本身,以便所有内容都保持在您放置的位置. 一种方法是编写一个类似于Canvas
.
这是一个原型BoundingCanvas
,它试图将其位置和大小限制在其子项的范围内:
public class BoundingCanvas : Panel
{
public BoundingCanvas()
{
HorizontalAlignment = HorizontalAlignment.Left;
VerticalAlignment = VerticalAlignment.Top;
}
private Vector minTopLeft;
protected override Size MeasureOverride(Size availableSize)
{
var resultSize = new Size();
minTopLeft = new Vector(double.PositiveInfinity, double.PositiveInfinity);
var unlimitedSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
foreach (UIElement child in Children)
{
child.Measure(unlimitedSize);
var topLeft = GetTopLeft(child);
minTopLeft.X = Math.Min(minTopLeft.X, topLeft.X);
minTopLeft.Y = Math.Min(minTopLeft.Y, topLeft.Y);
resultSize.Width = Math.Max(resultSize.Width, topLeft.X + child.DesiredSize.Width);
resultSize.Height = Math.Max(resultSize.Height, topLeft.Y + child.DesiredSize.Height);
}
resultSize.Width -= minTopLeft.X;
resultSize.Height -= minTopLeft.Y;
return resultSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
Margin = new Thickness(minTopLeft.X, minTopLeft.Y, 0, 0);
foreach (UIElement child in Children)
child.Arrange(new Rect(GetTopLeft(child) - minTopLeft, child.DesiredSize));
return finalSize;
}
private Point GetTopLeft(UIElement element)
{
return new Point(Canvas.GetLeft(element), Canvas.GetTop(element));
}
}
你可以像这样使用它:
<Grid>
<local:BoundingCanvas Background="Pink">
<Rectangle Canvas.Top="10" Canvas.Left="10" Width="10" Height="10" Fill="DarkRed"/>
<Rectangle Canvas.Top="20" Canvas.Left="20" Width="10" Height="10" Fill="DarkRed"/>
</local:BoundingCanvas>
</Grid>
原型需要更多的错误检查和特殊情况处理,但它展示了这个概念。在此示例中,面板使用额外的边距补偿调整后的大小,但您也可以操作Canvas.Top
,Canvas.Left
如果预期的父级是Canvas
.