Stackpanel:高度vs ActualHeight vs ExtentHeight vs ViewportHeight vs DesiredSize vs RenderSize

Ian*_*oyd 24 wpf height layout scaling stackpanel

我想知道我所有物品的高度StackPanel.

有什么区别:

  • Height - 获取或设置元素的建议高度.
  • ActualHeight - 获取此元素的渲染高度.(只读)
  • ExtentHeight - 获取包含范围的垂直大小的值.(只读)
  • ViewportHeight - 获取包含内容视口的垂直大小的值.(只读)
  • DesiredSize - 获取此元素在布局过程的度量传递期间计算的大小.(只读)
  • RenderSize - 获取(或设置,但请参阅备注)此元素的最终渲染大小.

来自MSDN:

Height
获取或设置元素的建议高度.

属性值:Double- 元素的高度,与设备无关的单位(每单位1/96英寸).

元件的高度,与设备无关的单位(每单位1/96英寸).

 

ActualHeight( readonly)
获取此元素的渲染高度.

属性值:Double- 元素的高度,作为与设备无关的单位中的值(每单位1/96英寸).

此属性是基于其他高度输入和布局系统的计算值.该值由布局系统本身根据实际渲染过程设置,因此可能略微落后于作为输入更改基础的高度等属性的设置值.

因为ActualHeight是一个计算值,所以您应该知道,由于布局系统的各种操作,可能会有多个或增量报告的更改.布局系统可以计算子元素所需的度量空间,父元素的约束等等.

 

ExtentHeight( readonly)
获取包含范围的垂直大小的值.

属性高度:Double- 表示范围的垂直大小的Double.

返回值在"设备无关像素"中描述.

 

ViewportHeight( readonly)
获取一个值,该值包含内容视口的垂直大小.

属性值:Double- 表示内容视口的垂直大小的Double.

返回值在"设备无关像素"中描述.

 

DesiredSize( readonly)
获取此元素在布局过程的度量传递期间计算的大小.

属性值:Size- 计算的大小,它成为排列过程的所需大小.

如果IsMeasureValid属性的值为true,则此属性返回的值仅为有效度量.

当您实现布局行为覆盖(例如,ArrangeOverride,MeasureOverride或OnRender)时,DesiredSize通常会被检查为测量因子之一(在OnRender情况下,您可能会检查RenderSize,但这取决于您的实现).根据场景,DesiredSize可能会被您的实现逻辑完全遵守,可能会应用DesiredSize的约束,并且此类约束也可能会更改父元素或子元素的其他特征.例如,支持可滚动区域的控件(但选择不从已启用可滚动区域的WPF框架级控件派生)可以将可用大小与DesiredSize进行比较.然后,控件可以设置内部状态,该UI在该UI中为该控件启用滚动条.或者,在某些情况下也可能会忽略DesiredSize.

 

RenderSize 获取此元素的最终渲染大小.

属性值:Size- 此元素的渲染大小.

此属性可用于检查布局系统覆盖(如OnRender或GetLayoutClip)中的适用渲染大小.

更常见的情况是使用类处理程序覆盖或OnRenderSizeChanged事件处理SizeChanged事件.


在我的情况下,我想知道所有项目的所需高度StackPanel.

换句话说:我想知道StackPanel中所有项目的高度(在绘图之前),如果它们溢出面板,我会

  • 删除
  • 收缩
  • 规模
  • 调整

确保它们适合StackPanel的项目.

这意味着我可能希望在调整大小事件(SizeChangedLayoutUpdated?)期间获得所需的高度(ExtentHeight?DesiredSize ?) - 在任何绘图发生之前(因此它更快).

大多数这些属性都返回零; 很明显,我对这些属性的含义有所了解,我不知道,也没有在文档中解释.

Nav*_*ani 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;
    }
}
Run Code Online (Sandbox Code Playgroud)
  • DesiredSize(返回的大小MeasureOverride)是StackPanel的方向和孩子最大的在其他方向上的大小尺寸的孩童的总和.

  • RenderSize表示StackPanel完成后布局的最终大小.

  • ActualHeight与...完全相同 RenderSize.Height.

要依赖这些属性,您应该只在LayoutUpdated事件的事件处理程序中访问它们.


Pet*_*ber 6

上面的答案是正确的,除了 RenderSize 和 ActualHeight 可以具有暂时不同的值。RenderSize 在 OnRender 之前设置,而 ActualHeight 在 WPF 完成该控件的布局和渲染处理后设置。最后,LayoutUpdated 被引发。

因此,RenderSize 可以在 OnRender 中使用,但 ActualHeight 仍将具有布局开始之前的旧值。

该序列如下所示:

MeasureOverride() => sets DesiredSize
ArrangeOverride() => sets RenderSize
OnRender()
Run Code Online (Sandbox Code Playgroud)

WPF 可能会多次执行此序列(递归)。一切确定后,将执行以下操作:

ActualHeight = RenderSize.Height
Run Code Online (Sandbox Code Playgroud)

ActualHeight 可以在第一次布局完成后的任何时间(!)访问,除了在测量、排列和渲染的布局过程本身期间。WPF 确保所有代码在布局处理运行之前完成。