Stackpanel: Height vs ActualHeight vs ExtentHeight vs ViewportHeight vs DesiredSize vs RenderSize

a 夏天 提交于 2019-12-02 18:08:29
Navid Rahmani

As you know the StackPanel is a [Panel] object. Each panel communicates with its children by two methods to determine the final sizes and positions. The first method is MeasureOverride and the second is ArrangeOverride.

The MeasureOveride asks each child for desired size with a given amount of space available. ArrangeOverride arranges the children after measurement has been completed.

Let's create a 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;
    }
}
  • The DesiredSize (the size returned by MeasureOverride) is sum of child sizes in the direction of StackPanel and the size of largest child in the other direction.

  • RenderSize represents the final size of the StackPanel after layout is complete.

  • ActualHeight is exactly same as RenderSize.Height.

For rely these properties you should access them only within an event handler for LayoutUpdated event.

Above answer is correct, except that RenderSize and ActualHeight can have temporarily different values. RenderSize gets set before OnRender, whereas ActualHeight gets set once WPF has finished the layout and render processing for that control. At the very end, LayoutUpdated gets raised.

Therefore, RenderSize can be used within OnRender, but ActualHeight will still have the old value from before the layout started.

The sequence looks like this:

MeasureOverride() => sets DesiredSize
ArrangeOverride() => sets RenderSize
OnRender()

WPF might execute this sequence several times (recursion). Once everything is settled, the following gets executed:

ActualHeight = RenderSize.Height

ActualHeight can be accessed any time (!) after the first layout is done, except during the layout process itself of measure, arrange and render. WPF ensures that any code gets completed before layout processing runs.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!