Измерение контроля с помощью double.PositiveInfinity WPF

Я работаю над пользовательским элементом управления с пользовательской панелью, и внутри пользовательской панели у меня есть небольшой и простой метод MeasureOverride, который передает размер double.PositiveInfinity своему дочернему методу MeasureOverride. Пользовательская панель должна заботиться о макете и должна делать дочерние элементы больше или меньше в зависимости от размера окна.

Если вы имели дело с элементами управления, вы должны знать, как работает система компоновки wpf и что в основном каждый дочерний элемент вызывает MeasureOverride, который вызывает MeasureOverride дочерних элементов и так далее.

Теперь проблема в том, что когда я изменяю размер окна, настраиваемая панель получает флаг для повторного измерения, поэтому MeasureOverride вызывается снова, но на этот раз при передаче размера double.PositiveInfitinty своим дочерним элементам дочерние элементы MeasureOverride не получают вызывается вообще (но метод должен вызываться в соответствии с определением системы компоновки WPF). Почему это так? Я всегда думал, что когда я вызываю MeasureOverride для родителя, дети также будут вынуждены делать это.

Очевидно, я ошибаюсь, так что может ли кто-нибудь объяснить мне, как контрольная группа/ребенок узнает, когда проводить повторные измерения?

Кстати, я передаю детям размер double.PositiveInfinity, чтобы они занимали столько места, сколько нужно.

Код:

protected override Size MeasureOverride(Size availableSize)
{
 double x;
 double y;
 var children = this.InternalChildren;
 for (int i = 0; i < children.Count; i++)
     {
       UIElement child = children[i];
       child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity);
       y += child.DesiredSize.Height;
       x = Math.Max(x, child.DesiredSize.Width);
      }
 return new Size(x, y);
}

Код прост. Я не понимаю, почему детей снова не измеряют. И извините, если я что-то неправильно написал в коде.


person cyberist    schedule 08.02.2013    source источник
comment
Пожалуйста, покажите нам свой код для метода MeasureOverride вашей пользовательской панели.   -  person Benjamin Gale    schedule 08.02.2013


Ответы (2)


Ваши дочерние элементы не будут измеряться снова, потому что им это не нужно: поскольку вы продолжаете передавать один и тот же размер, WPF знает, что нет необходимости измерять снова, поскольку результирующий DesiredSize будет таким же.

При этом Desiredsize, обновленный Measure, — это только тот размер, который ваш ребенок считает наиболее подходящим. Вы должны учитывать это при переопределении ArrangeOverride, но вы не обязаны: просто расположите своих детей так, как вам нравится, тот факт, что MeasureOverride называется или нет для ваших детей, не должен иметь значения.

person Julien Lebosquain    schedule 08.02.2013
comment
Означает ли это, что они никогда больше не будут измеряться, так как я всегда буду передавать их double.PositiveInfinity? Мне нужно позвонить им, чтобы измерить. Когда размер окна изменился, каждый дочерний элемент необходимо измерить, поскольку дочерние элементы имеют определенную логику измерения. - person cyberist; 08.02.2013
comment
Затем вы должны измерить элемент с заданным ограничением или вам нужно как-то уведомить элементы об изменении размера и аннулировать их меру. Обратите внимание, конечно, что аннулирование меры просто загрязняет этот элемент, а не какие-либо из его потомков или его предков, поэтому, если вы полагаетесь на изменение DesiredSize, вам нужно будет подняться по дереву элементов и аннулировать все меры до вашего панель, которая создает довольно тесную связь между этими дочерними элементами и панелью. - person AndrewS; 08.02.2013
comment
скажем, моя панель имеет размер 300x300, а затем я изменяю размер ширины одного дочернего элемента на 400. как я могу сказать своей панели сделать панель недействительной, если с дочерним элементом › 300, как в этом случае? - person cyberist; 09.02.2013
comment
@AndrewS, не могли бы вы помочь мне, как сказать родителям, чтобы они соответствовали размеру детей? - person cyberist; 09.02.2013
comment
@cyberist: Чего вы на самом деле пытаетесь достичь? Не передавайте PositiveInfinity, если ваши дочерние элементы должны быть ограничены определенным размером: передайте доступный размер, и ваши дочерние элементы будут снова измерены. - person Julien Lebosquain; 09.02.2013
comment
Я запускаю измерение обновления для любого дочернего элемента, и я хочу, чтобы родитель также снова измерял. - person cyberist; 09.02.2013
comment
@cyberist Ребенок не говорит родителю, как он должен его измерить / измерить / расположить. Родитель будет измерять дочерний элемент с некоторым ограничением — обычно либо с бесконечностью, либо с некоторой частью ограничения, которое ему было дано. Затем родитель обычно (но не всегда) использует DesiredSize этого элемента при его размещении. Если произойдет что-то, что сделает измерение этого дочернего объекта недействительным позже, оно будет повторно измерено с тем же ограничением, с которым оно было измерено в последний раз. Если то, что он возвращает, отличается от последнего, то вызывается OnDesiredSizeChanged родителя, и его мера становится недействительной. - person AndrewS; 11.02.2013
comment
Тогда это может означать, что этот элемент вернет другой размер для DesiredSize, поэтому его родитель может стать недействительным. И он идет вверх по дереву, если не останавливается по пути. - person AndrewS; 11.02.2013
comment
Как родитель узнает, когда изменяется desizeSize дочернего элемента? - person cyberist; 11.02.2013

Вы пытались вызвать UIElement.InvalidateMeasure, где UIElement — ваша родительская панель?

person sacha barber    schedule 08.02.2013