web-dev-qa-db-ja.com

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

StackPanelのすべてのアイテムの高さを知りたい。

違いは何ですか:

  • Height -要素の推奨される高さを取得または設定します。
  • ActualHeight -この要素のレンダリングされた高さを取得します。 (読み取り専用
  • ExtentHeight -エクステントの垂直サイズを含む値を取得します。 (読み取り専用
  • ViewportHeight -コンテンツのビューポートの垂直方向のサイズを含む値を取得します。 (読み取り専用
  • DesiredSize -レイアウトプロセスのメジャーパス中にこの要素が計算したサイズを取得します。 (読み取り専用
  • RenderSize -この要素の最終的なレンダリングサイズを取得(または設定しますが、備考を参照)します。

MSDNから:

高さ
要素の推奨高さを取得または設定します。

プロパティ値:Double-要素の高さ(デバイスに依存しない単位)(単位あたり1/96インチ)。

要素の高さ(デバイスに依存しない単位)(単位あたり1/96インチ)。

ActualHeight読み取り専用
この要素のレンダリングされた高さを取得します。

プロパティ値:Double-デバイスに依存しない単位の値としての要素の高さ(単位あたり1/96インチ)。

このプロパティは、他の高さ入力とレイアウトシステムに基づいて計算された値です。この値は、実際のレンダリングパスに基づいてレイアウトシステム自体によって設定されるため、入力変更の基礎となる Height などのプロパティの設定値よりもわずかに遅れる場合があります。

ActualHeightは計算値であるため、レイアウトシステムによるさまざまな操作の結果として、複数または増分の変更が報告される可能性があることに注意してください。レイアウトシステムは、子要素に必要な測定スペース、親要素による制約などを計算している場合があります。

ExtentHeight読み取り専用
エクステントの垂直サイズを含む値を取得します。

プロパティの高さ:Double-エクステントの垂直方向のサイズを表すDouble。

戻り値は、デバイスに依存しないピクセルで説明されています。

ViewportHeight読み取り専用
コンテンツのビューポートの垂直方向のサイズを含む値を取得します。

プロパティ値:Double-コンテンツのビューポートの垂直方向のサイズを表すDouble。

戻り値は、デバイスに依存しないピクセルで説明されています。

DesiredSizereadonly
レイアウトプロセスのメジャーパス中にこの要素が計算したサイズを取得します。

プロパティ値:Size-計算されたサイズ。これがアレンジパスの目的のサイズになります。

このプロパティによって返される値は、IsMeasureValidプロパティの値がtrueの場合にのみ有効な測定値になります。

通常、DesiredSizeは、ArrangeOverride、MeasureOverride、OnRenderなどのレイアウト動作オーバーライドを実装するときに測定要素の1つとしてチェックされます(OnRenderの場合、代わりにRenderSizeをチェックできますが、これは実装によって異なります)。シナリオによっては、DesiredSizeが実装ロジックによって完全に尊重され、DesiredSizeの制約が適用される場合があり、そのような制約によって、親要素または子要素のいずれかの他の特性も変更される場合があります。たとえば、スクロール可能な領域をサポートするコントロール(ただし、スクロール可能な領域を既に有効にしているWPFフレームワークレベルのコントロールから派生しないことを選択する)は、使用可能なサイズをDesiredSizeと比較できます。次に、コントロールは、そのコントロールのUIでスクロールバーを有効にする内部状態を設定できます。または、特定のシナリオでは、DesiredSizeも無視される可能性があります。

RenderSizeこの要素の最終的なレンダリングサイズを取得します。

プロパティ値:Size-この要素のレンダリングサイズ。

このプロパティは、OnRenderやGetLayoutClipなどのレイアウトシステムオーバーライド内で適用可能なレンダーサイズを確認するために使用できます。

より一般的なシナリオは、クラスハンドラーのオーバーライドまたはOnRenderSizeChangedイベントを使用してSizeChangedイベントを処理することです。


私の場合、StackPanel内のすべてのアイテムのdesiredの高さを知りたいです。

言い換えると、StackPanel内のすべてのアイテムの高さを(描画する前に)知りたいのですが、それらがパネルからオーバーフローした場合は、

  • 削除
  • シュリンク
  • 規模
  • 調整する

StackPanelに確実に収まるようにするアイテム。

つまり、resizeイベント中にdesiredheight(ExtentHeight?DesiredSize?)を取得したいということです( SizeChangedLayoutUpdated ?)-描画が行われる前(したがって、より高速です)。

これらのプロパティのほとんどはゼロを返します。したがって、これらのプロパティが何を意味するのかについては、私が知らず、ドキュメントで説明されていないことをある程度理解していることは明らかです。

24
Ian Boyd

ご存知のように、StackPanelは[Panel]オブジェクトです。各パネルは、2つの方法で子と通信して、最終的なサイズと位置を決定します。最初のメソッドはMeasureOverrideで、2番目のメソッドはArrangeOverrideです。

MeasureOverideは、各子に、指定された空き容量で希望のサイズを尋ねます。 ArrangeOverrideは、測定が完了した後に子を配置します。

スタックパネルを作成しましょう:

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;
    }
}
  • DesiredSizeMeasureOverrideによって返されるサイズ)は、StackPanelの方向の子のサイズと、他の方向の最大の子のサイズの合計です。

  • RenderSizeは、レイアウトが完了した後のStackPanelの最終的なサイズを表します。

  • ActualHeightRenderSize.Heightとまったく同じです。

これらのプロパティを信頼するには、 LayoutUpdated イベントのイベントハンドラー内でのみアクセスする必要があります。

14
Navid Rahmani

RenderSizeとActualHeightが一時的に異なる値を持つ可能性があることを除いて、上記の答えは正しいです。 RenderSizeはOnRenderの前に設定されますが、ActualHeightは、WPFがそのコントロールのレイアウトとレンダリング処理を完了すると設定されます。最後に、LayoutUpdatedが発生します。

したがって、RenderSizeはOnRender内で使用できますが、ActualHeightには、レイアウトが開始される前の古い値が引き続き含まれます。

シーケンスは次のようになります。

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

WPFは、このシーケンスを数回実行する場合があります(再帰)。すべてが解決すると、以下が実行されます。

ActualHeight = RenderSize.Height

ActualHeightは、最初のレイアウトが完了した後、いつでも(!)アクセスできます。ただし、測定、配置、およびレンダリングのレイアウトプロセス自体は除きます。 WPFは、レイアウト処理が実行される前にコードが完了することを保証します。

3
Peter Huber