Почему ListBoxItem не вызывает MeasureOverride при изменении его ширины? - PullRequest
1 голос
/ 05 октября 2011

Хорошо, для наглядности ниже я создал подкласс ListBoxItem и подкласс ListBox, который использует его в качестве контейнера, переопределяя как IsItemItsOwnContainerOverride, так и GetContainerForItemOverride.

Теперь, когдасначала появляется окно, как и ожидалось, MeasureOverride вызывается для каждого ListBoxItem (с бесконечностью, бесконечностью), за которым следует ArrangeOverride для каждого элемента.

Однако при изменении размера ListBox,на ListBoxItem вызывается только ArrangeOverride, а не MeasureOverride, хотя метаданные для свойства width установлены на AffectsMeasure.

Примечание: я знаю, что могу обойти этоустановка ScrollViewer.HorizontalScrollbarVisibility на «Отключено», в этом случае MeasureOverride вызывается, как и ожидалось, потому что эта настройка прокрутки заставляет элементы соответствовать ширине списка и, таким образом, естественно перезапускается.Тем не менее, я все еще пытаюсь выяснить, почему Measure не вызывается по умолчанию, так как метаданные для свойства Width имеют установленный флаг AffectsMeasure, а ширина изменяется с помощью шага ArrangeOverride.

Является ли этот флаг просто подсказкой для его контейнера, и в случае элемента управления, помещенного в ScrollViewer, он игнорируется?Я предполагаю, что, если вы не отключите прокрутку, у элементов управления будет бесконечная область, доступная для них, поэтому после их измерения нет необходимости повторно измерять их снова.Отключите горизонтальную прокрутку, и вы заявляете, что ширина не безгранична, поэтому MeasureOverride вызывается снова.Но это всего лишь предположение, хотя и логичное.

Вот пример кода для игры.Создайте новый проект WPF и вставьте его в CodeBehind окна и посмотрите на результаты отладки.Затем установите флаг HorizontalScrollbarVisibility, и вы увидите, что он вызывается.

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);
    }

}

1 Ответ

0 голосов
/ 14 декабря 2015

Хорошо, я думаю, что ответ заключается в том, что он не запускается, потому что проход Измерение влияет на панель, а не на элементы, а сама панель не изменила размер, поэтому нет причин повторно измерять ее дочерние элементы.

Однако при установке ScrollViewer.HorizontalScrollbarVisibility на Disabled ширина панели отслеживает ширину ListBox, а не его содержимое, поэтому дочерние элементы необходимо повторно измерять, поэтому они и были в этом случае.

...