Wpf 制作控件的简单方法';s边界更改以适应动态内容?
我想要一个控件的边界调整大小,以适应它的所有动态内容,这会改变每一帧。换句话说,如果我通过任何方式(画布、边框等)在控件上显示边界框,则该框应包含所有可见内容,其中可见内容的左上角是框的左上角。所有东西都应该放在盒子里 内容的特殊之处在于,它们会更改每一帧,并根据外部源的参数绘制整个位置。我将控件的当前高度和宽度设置为“自动”-这可以很好地确保显示所有内容-但不幸的是,控件的左上角值不会对应于所有可见内容的左上角Wpf 制作控件的简单方法';s边界更改以适应动态内容?,wpf,wpf-controls,bounds,Wpf,Wpf Controls,Bounds,我想要一个控件的边界调整大小,以适应它的所有动态内容,这会改变每一帧。换句话说,如果我通过任何方式(画布、边框等)在控件上显示边界框,则该框应包含所有可见内容,其中可见内容的左上角是框的左上角。所有东西都应该放在盒子里 内容的特殊之处在于,它们会更改每一帧,并根据外部源的参数绘制整个位置。我将控件的当前高度和宽度设置为“自动”-这可以很好地确保显示所有内容-但不幸的是,控件的左上角值不会对应于所有可见内容的左上角 是否有一种简单的方法使控件的边界更改为包含其所有内容?如上所述,如果我显示一个边界
是否有一种简单的方法使控件的边界更改为包含其所有内容?如上所述,如果我显示一个边界框,该框应该只包含所有可见内容。您没有说明如何定位控件的子元素,但子元素与控件相对,因此您需要控件收缩其左侧和顶部空白区域,然后移动控件本身,以便所有内容都保持在您放置的位置。一种方法是编写一个类似于
画布的自定义面板
下面是一个原型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
,您也可以操作Canvas.Top
和Canvas.Left
,我感谢您的回答。为什么要执行子.Measure(未限制大小)
?我不太确定我是否理解度量的作用,即使在阅读了文档之后。另外,在您的GetTopLeft
函数中,如何获得使用边距定位的渲染转换或布局转换元素的左上角位置?我让我的BoundedCanvas像一个真实的画布一样运行,它会询问其子代“您有多大,顺便说一句,您可以达到您想要的大小”。对于margin,您可以使用它来代替Canvas.Top和Canvas.Left,也可以将其添加到Canvas.Top和Canvas.Left中。LayoutTransform将显示在DesiredSize中,您无需特殊处理。由于我们所做的是与布局相关的,所以根据定义不应考虑RenderTransform。很好,非常感谢您的帮助。这给了我一个好主意,我应该从这里做什么。