1

分かりやすく説明するために、以下では、と の両方をオーバーライドしてListBoxItem、 のサブクラスと のサブクラスを作成ListBoxし、コンテナとしてそれを使用しています。IsItemItsOwnContainerOverrideGetContainerForItemOverride

ウィンドウが最初に表示されると、予想どおり、MeasureOverride( ListBoxItemInfinity,Infinity を使用して)ArrangeOverrideすべてのアイテムで呼び出され、その後すべてのアイテムで呼び出されます。

ただし、 のサイズを変更する場合、 width プロパティのメタデータが に設定されていても、ListBoxのみArrangeOverrideが呼び出されます。ListBoxItemMeasureOverrideAffectsMeasure

注:ScrollViewer.HorizontalScrollbarVisibility「無効」に設定することでこれを回避できることはわかってMeasureOverrideいます。この場合、スクロール設定によりアイテムがリストボックスの幅に一致するように強制され、自然に再起動されるため、期待どおりに呼び出されます。Widthただし、プロパティのメタデータにAffectsMeasureフラグが設定されており、ステップによって幅が変化しているため、デフォルトで Measure が呼び出されない理由をまだ理解しようとしていますArrangeOverride

そのフラグはコンテナの単なるヒントであり、コントロールが配置されている場合はScrollViewer無視されますか? 私の推測では、スクロールを無効にしない限り、コントロールは無限の領域を使用できるため、一度測定すると、再度測定する必要はありません。ただし、水平スクロールを無効にすると、幅が無制限ではないため、MeasureOverrideが再度呼び出されます。しかし、それは論理的なものではありますが、単なる推測です。

ここで遊ぶためのサンプルコードです。新しい WPF プロジェクトを作成し、これをウィンドウの CodeBehind に貼り付けて、デバッグ出力を確認します。次に、Horizo​​ntalScrollbarVisibility フラグを設定すると、それが呼び出されることがわかります。

public partial class MainWindow : Window
{
    public MainWindow(){
        InitializeComponent();
        var items = new List<object>(){ "This is a really, really, really, really long sentence"};
        var lbx = new ListBoxEx { ItemsSource = items };
        this.Content = lbx;
    }

}

public class ListBoxEx : ListBox
{
    protected override bool IsItemItsOwnContainerOverride(object item){
        return (item is ListBoxItemEx);
    }

    protected override DependencyObject GetContainerForItemOverride(){
        return new ListBoxItemEx();
    }
}

public class ListBoxItemEx : ListBoxItem
{
    protected override Size MeasureOverride(Size availableSize){
        Console.WriteLine("MeasureOverride called with " + availableSize);
        return base.MeasureOverride(availableSize);
    }

    protected override Size ArrangeOverride(Size finalSize){
        Console.WriteLine("ArrangeOverride called with " + finalSize);
        return base.ArrangeOverride(finalSize);
    }

}
4

1 に答える 1