MeasureOverride не работает на холсте

Мне нужно изменить размер прямоугольника, размещенного на холсте, поэтому я унаследовал Canvas для использования MeasureOverride:

public class CustomCanvas : Canvas
{
    public CustomCanvas() : base(){}

    protected override Size MeasureOverride(Size availableSize)
    {
        Size canvasDesiredSize = new Size();

        foreach (UIElement child in Children)
        {
            child.Measure(new Size(300, 300));
            canvasDesiredSize = child.DesiredSize;
        }

        return canvasDesiredSize;
    }
}

И использовал это:

<local:CustomCanvas Width="500" Height="800" Background="Gray">
        <Rectangle Fill="AliceBlue" Height="100" Width="100"/>
    </local:CustomCanvas>

Но после выполнения прямоугольник по-прежнему имеет размер 100 100 (как указано в XAML). При выполнении child.Measure(new Size(300, 300)); child.DesiredSize показывает 0,0. Там происходит что-то странное.

Я использовал это в качестве ссылки.


person Anthony    schedule 06.08.2014    source источник
comment
Я пытался сделать абсолютно то же самое в элементе управления Panel, и прямоугольник вообще не виден, несмотря на то, что child.DesiredSize показывает 100 100 (как в XAML).   -  person Anthony    schedule 06.08.2014


Ответы (1)


Короткий ответ заключается в том, что ширина и высота переопределяют любой размер, заданный в Measure().

В документации Microsoft отсутствует важная информация о потоке данных между Measure() и MeasureOverride().

Контейнер вызывает Child.Measure()
Measure() вызывает MeasureCore()
MeasureCore() вызывает MeasureOverride()

Measure — это метод UIElement.
MeasureCore — это метод FrameworkElement, который наследуется от UIElement. MeasureOverride — это метод FrameworkElement. MeasureOverride переопределяется дочерним элементом.

UIElement.Measure(avialableSize) перед вызовом MeasurementCore() делает следующее:

  • выдает исключение, если avialableSize IsNan, как для ширины, так и для высоты
  • если UIElement свернут, MeasureCore не будет вызываться
  • если availableSize не изменился, MeasureCore не будет вызываться, если до этого не был вызван InvalidateMeasure
  • вызов InvalidateArrange

FrameworkElement.MeasurementCore(availableSize) перед вызовом MeasureOverride() делает следующее:

  • удаляет Margin из availableSize
  • применяет высоту, minHeight и maxHeight поверх availableSize и то же самое для свойств ширины

после вызова MeasureOverride() MeasurementCore() корректирует значения, возвращаемые MeasureOverride(), для вычисления DesiredSize:

  • DesiredSize должен быть в пределах MinWidth и MaxWidth
  • добавить маржу в DesiredSize

после вызова FrameworkElement.MeasurementCore() UIElement.Measure() выполняет:

  • выдает исключение, если возвращаемая ширина или высота бесконечны
  • выдает исключение, если возвращаемая ширина или высота равна NaN
person Peter Huber    schedule 17.01.2015