答案 0 :(得分:14)
如您所知StackPanel
是[Panel]对象。每个小组通过两种方法与其子女沟通,以确定最终的大小和位置。
第一种方法是MeasureOverride
,第二种方法是ArrangeOverride
。
MeasureOveride
在给定数量的可用空间的情况下询问每个孩子所需的大小。
测量完成后ArrangeOverride
安排孩子们。
让我们创建一个stackpanel:
public class AnotherStackPanel : Panel
{
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register(“Orientation”, typeof(Orientation),
typeof(SimpleStackPanel), new FrameworkPropertyMetadata(
Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsMeasure));
public Orientation Orientation
{
get { return (Orientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
protected override Size MeasureOverride(Size availableSize)
{
Size desiredSize = new Size();
if (Orientation == Orientation.Vertical)
availableSize.Height = Double.PositiveInfinity;
else
availableSize.Width = Double.PositiveInfinity;
foreach (UIElement child in this.Children)
{
if (child != null)
{
child.Measure(availableSize);
if (Orientation == Orientation.Vertical)
{
desiredSize.Width = Math.Max(desiredSize.Width,
child.DesiredSize.Width);
desiredSize.Height += child.DesiredSize.Height;
}
else
{
desiredSize.Height = Math.Max(desiredSize.Height,
child.DesiredSize.Height);
desiredSize.Width += child.DesiredSize.Width;
}
}
}
return desiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
double offset = 0;
foreach (UIElement child in this.Children)
{
if (child != null)
{
if (Orientation == Orientation.Vertical)
{
child.Arrange(new Rect(0, offset, finalSize.Width,
child.DesiredSize.Height));
offset += child.DesiredSize.Height;
}
else
{
child.Arrange(new Rect(offset, 0, child.DesiredSize.Width,
finalSize.Height));
offset += child.DesiredSize.Width;
}
}
}
return finalSize;
}
}
DesiredSize
(大小
MeasureOverride
)返回的是总和
儿童大小的方向
StackPanel的大小最大
孩子在另一个方向。
RenderSize
代表决赛
布局后StackPanel
的大小
已经完成了。
ActualHeight
与...完全相同
RenderSize.Height
。要依赖这些属性,您应该只在LayoutUpdated事件的事件处理程序中访问它们。
答案 1 :(得分:3)
以上答案是正确的,但RenderSize和ActualHeight可以暂时具有不同的值。 RenderSize在OnRender之前设置,而一旦WPF完成布局并为该控件渲染处理,ActualHeight就会被设置。最后,LayoutUpdated会被提升。
因此,RenderSize可以在OnRender中使用,但ActualHeight仍将具有布局开始之前的旧值。
序列如下所示:
MeasureOverride() => sets DesiredSize
ArrangeOverride() => sets RenderSize
OnRender()
WPF可能会多次执行此序列(递归)。一切都解决后,执行以下操作:
ActualHeight = RenderSize.Height
在第一次布局完成后,可以随时(!)访问ActualHeight,除了在测量,排列和渲染的布局过程中。 WPF确保在布局处理运行之前完成任何代码。