@@ -202,12 +202,8 @@ public override SizeRequest Measure(double widthConstraint, double heightConstra
202202 SizeRequest size = base . Measure ( widthConstraint - Padding . HorizontalThickness , heightConstraint - Padding . VerticalThickness , flags ) ;
203203#pragma warning restore CS0618 // Type or member is obsolete
204204#pragma warning disable CS0618 // Type or member is obsolete
205- var request = new Size ( size . Request . Width + Padding . HorizontalThickness , size . Request . Height + Padding . VerticalThickness ) ;
206- var minimum = new Size ( size . Minimum . Width + Padding . HorizontalThickness , size . Minimum . Height + Padding . VerticalThickness ) ;
207-
208- DesiredSize = request ;
209-
210- return new SizeRequest ( request , minimum ) ;
205+ return new SizeRequest ( new Size ( size . Request . Width + Padding . HorizontalThickness , size . Request . Height + Padding . VerticalThickness ) ,
206+ new Size ( size . Minimum . Width + Padding . HorizontalThickness , size . Minimum . Height + Padding . VerticalThickness ) ) ;
211207#pragma warning restore CS0618 // Type or member is obsolete
212208 }
213209#pragma warning restore CS0672 // Member overrides obsolete member
@@ -324,19 +320,14 @@ public void RaiseChild(View view)
324320 [ Obsolete ( "Use InvalidateMeasure depending on your scenario" ) ]
325321 protected virtual void InvalidateLayout ( )
326322 {
327- SetNeedsLayout ( ) ;
323+ _hasDoneLayout = false ;
328324 InvalidateMeasureInternal ( InvalidationTrigger . MeasureChanged ) ;
329325 if ( ! _hasDoneLayout )
330326 {
331327 ForceLayout ( ) ;
332328 }
333329 }
334330
335- void SetNeedsLayout ( )
336- {
337- _hasDoneLayout = false ;
338- }
339-
340331 /// <summary>
341332 /// Positions and sizes the children of a layout.
342333 /// </summary>
@@ -350,18 +341,10 @@ void SetNeedsLayout()
350341 [ Obsolete ( "Use ArrangeOverride" ) ]
351342 protected abstract void LayoutChildren ( double x , double y , double width , double height ) ;
352343
353- internal override void OnChildMeasureInvalidated ( VisualElement child , InvalidationTrigger trigger )
344+ internal override void OnChildMeasureInvalidatedInternal ( VisualElement child , InvalidationTrigger trigger , int depth )
354345 {
355- SetNeedsLayout ( ) ;
356- InvalidateMeasureCache ( ) ;
357-
358- OnChildMeasureInvalidated ( child , new InvalidationEventArgs ( trigger ) ) ;
359-
360- var propagatedTrigger = GetPropagatedTrigger ( trigger ) ;
361- InvokeMeasureInvalidated ( propagatedTrigger ) ;
362-
363- // Behavior of legacy layouts is to always propagate the measure invalidation to the parent
364- ( Parent as VisualElement ) ? . OnChildMeasureInvalidated ( this , propagatedTrigger ) ;
346+ // TODO: once we remove old Xamarin public signatures we can invoke `OnChildMeasureInvalidated(VisualElement, InvalidationTrigger)` directly
347+ OnChildMeasureInvalidated ( child , new InvalidationEventArgs ( trigger , depth ) ) ;
365348 }
366349
367350 /// <summary>
@@ -373,6 +356,19 @@ internal override void OnChildMeasureInvalidated(VisualElement child, Invalidati
373356 /// <remarks>This method has a default implementation and application developers must call the base implementation.</remarks>
374357 protected void OnChildMeasureInvalidated ( object sender , EventArgs e )
375358 {
359+ var depth = 0 ;
360+ InvalidationTrigger trigger ;
361+ if ( e is InvalidationEventArgs args )
362+ {
363+ trigger = args . Trigger ;
364+ depth = args . CurrentInvalidationDepth ;
365+ }
366+ else
367+ {
368+ trigger = InvalidationTrigger . Undefined ;
369+ }
370+
371+ OnChildMeasureInvalidated ( ( VisualElement ) sender , trigger , depth ) ;
376372 OnChildMeasureInvalidated ( ) ;
377373 }
378374
@@ -546,6 +542,55 @@ internal static void LayoutChildIntoBoundingRegion(View child, Rect region, Size
546542 child . Layout ( region ) ;
547543 }
548544
545+ internal virtual void OnChildMeasureInvalidated ( VisualElement child , InvalidationTrigger trigger , int depth )
546+ {
547+ IReadOnlyList < Element > children = LogicalChildrenInternal ;
548+ int count = children . Count ;
549+ for ( var index = 0 ; index < count ; index ++ )
550+ {
551+ if ( LogicalChildrenInternal [ index ] is VisualElement v && v . IsVisible && ( ! v . IsPlatformEnabled || ! v . IsPlatformStateConsistent ) )
552+ {
553+ return ;
554+ }
555+ }
556+
557+ if ( child is View view )
558+ {
559+ // we can ignore the request if we are either fully constrained or when the size request changes and we were already fully constrained
560+ if ( ( trigger == InvalidationTrigger . MeasureChanged && view . Constraint == LayoutConstraint . Fixed ) ||
561+ ( trigger == InvalidationTrigger . SizeRequestChanged && view . ComputedConstraint == LayoutConstraint . Fixed ) )
562+ {
563+ return ;
564+ }
565+ if ( trigger == InvalidationTrigger . HorizontalOptionsChanged || trigger == InvalidationTrigger . VerticalOptionsChanged )
566+ {
567+ ComputeConstraintForView ( view ) ;
568+ }
569+ }
570+
571+ InvalidateMeasureLegacy ( trigger , depth , int . MaxValue ) ;
572+ }
573+
574+ // This lets us override the rules for invalidation on MAUI controls that unfortunately still inheirt from the legacy layout
575+ private protected virtual void InvalidateMeasureLegacy ( InvalidationTrigger trigger , int depth , int depthLeveltoInvalidate )
576+ {
577+ if ( depth <= depthLeveltoInvalidate )
578+ {
579+ if ( trigger == InvalidationTrigger . RendererReady )
580+ {
581+ InvalidateMeasureInternal ( new InvalidationEventArgs ( InvalidationTrigger . RendererReady , depth ) ) ;
582+ }
583+ else
584+ {
585+ InvalidateMeasureInternal ( new InvalidationEventArgs ( InvalidationTrigger . MeasureChanged , depth ) ) ;
586+ }
587+ }
588+ else
589+ {
590+ FireMeasureChanged ( trigger , depth ) ;
591+ }
592+ }
593+
549594 internal override void OnIsVisibleChanged ( bool oldValue , bool newValue )
550595 {
551596 base . OnIsVisibleChanged ( oldValue , newValue ) ;
@@ -663,6 +708,19 @@ bool ShouldLayoutChildren()
663708 return true ;
664709 }
665710
711+ protected override void InvalidateMeasureOverride ( )
712+ {
713+ base . InvalidateMeasureOverride ( ) ;
714+
715+ foreach ( var child in ( ( IElementController ) this ) . LogicalChildren )
716+ {
717+ if ( child is IView fe )
718+ {
719+ fe . InvalidateMeasure ( ) ;
720+ }
721+ }
722+ }
723+
666724 protected override Size ArrangeOverride ( Rect bounds )
667725 {
668726 base . ArrangeOverride ( bounds ) ;
0 commit comments