diff --git a/src/Core/src/Handlers/Element/ElementHandler.cs b/src/Core/src/Handlers/Element/ElementHandler.cs index 47ef3fcd97a1..e221d62776b4 100644 --- a/src/Core/src/Handlers/Element/ElementHandler.cs +++ b/src/Core/src/Handlers/Element/ElementHandler.cs @@ -32,6 +32,8 @@ protected ElementHandler(IPropertyMapper mapper, CommandMapper? commandMapper = public IElement? VirtualView { get; private protected set; } + internal bool _isPlatformViewNew; + public virtual void SetMauiContext(IMauiContext mauiContext) => MauiContext = mauiContext; @@ -47,10 +49,21 @@ public virtual void SetVirtualView(IElement view) bool setupPlatformView = oldVirtualView == null; VirtualView = view; - PlatformView ??= CreatePlatformElement(); + + bool isNew = false; + + if (PlatformView is null) + { + PlatformView = CreatePlatformElement(); + isNew = true; + } + + _isPlatformViewNew = isNew; if (VirtualView.Handler != this) + { VirtualView.Handler = this; + } // We set the previous virtual view to null after setting it on the incoming virtual view. // This makes it easier for the incoming virtual view to have influence @@ -77,6 +90,8 @@ public virtual void SetVirtualView(IElement view) } _mapper.UpdateProperties(this, VirtualView); + + _isPlatformViewNew = false; } public virtual void UpdateValue(string property) diff --git a/src/Core/src/Platform/Windows/TransformationExtensions.cs b/src/Core/src/Platform/Windows/TransformationExtensions.cs index d865a90f060f..c41cd671ca31 100644 --- a/src/Core/src/Platform/Windows/TransformationExtensions.cs +++ b/src/Core/src/Platform/Windows/TransformationExtensions.cs @@ -19,8 +19,13 @@ public static void UpdateTransformation(this FrameworkElement frameworkElement, if (rotationX % 360 == 0 && rotationY % 360 == 0 && rotation % 360 == 0 && translationX == 0 && translationY == 0 && scaleX == 1 && scaleY == 1) { - frameworkElement.Projection = null; - frameworkElement.RenderTransform = null; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false; + + if (skipInitialization != true) + { + frameworkElement.Projection = null; + frameworkElement.RenderTransform = null; + } } else { diff --git a/src/Core/src/Platform/Windows/ViewExtensions.cs b/src/Core/src/Platform/Windows/ViewExtensions.cs index 02b0f765a6f4..a73ca8fe2b3c 100644 --- a/src/Core/src/Platform/Windows/ViewExtensions.cs +++ b/src/Core/src/Platform/Windows/ViewExtensions.cs @@ -43,29 +43,35 @@ public static void Unfocus(this FrameworkElement platformView, IView view) public static void UpdateVisibility(this FrameworkElement platformView, IView view) { - double opacity = view.Opacity; - var wasCollapsed = platformView.Visibility == UI.Xaml.Visibility.Collapsed; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !(view.Visibility == Visibility.Visible && view.Opacity == 1.0); - switch (view.Visibility) + if (skipInitialization != true) { - case Visibility.Visible: - platformView.Opacity = opacity; - platformView.Visibility = UI.Xaml.Visibility.Visible; - break; - case Visibility.Hidden: - platformView.Opacity = 0; - platformView.Visibility = UI.Xaml.Visibility.Visible; - break; - case Visibility.Collapsed: - platformView.Opacity = opacity; - platformView.Visibility = UI.Xaml.Visibility.Collapsed; - break; - } + double opacity = view.Opacity; + var wasCollapsed = platformView.Visibility == UI.Xaml.Visibility.Collapsed; - if (view.Visibility != Visibility.Collapsed && wasCollapsed) - { - // We may need to force the parent layout (if any) to re-layout to accomodate the new size - (platformView.Parent as FrameworkElement)?.InvalidateMeasure(); + switch (view.Visibility) + { + case Visibility.Visible: + platformView.Opacity = opacity; + platformView.Visibility = UI.Xaml.Visibility.Visible; + break; + case Visibility.Hidden: + platformView.Opacity = 0; + platformView.Visibility = UI.Xaml.Visibility.Visible; + break; + case Visibility.Collapsed: + platformView.Opacity = opacity; + platformView.Visibility = UI.Xaml.Visibility.Collapsed; + break; + } + + if (view.Visibility != Visibility.Collapsed && wasCollapsed) + { + // We may need to force the parent layout (if any) to re-layout to accomodate the new size + (platformView.Parent as FrameworkElement)?.InvalidateMeasure(); + } } } @@ -95,8 +101,13 @@ public static void UpdateBorder(this FrameworkElement platformView, IView view) public static void UpdateOpacity(this FrameworkElement platformView, IView view) { var opacity = view.Visibility == Visibility.Hidden ? 0 : view.Opacity; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || opacity != 1; - platformView.UpdateOpacity(opacity); + if (skipInitialization != true) + { + platformView.UpdateOpacity(opacity); + } } internal static void UpdateOpacity(this FrameworkElement platformView, double opacity) => platformView.Opacity = (float)opacity; @@ -122,23 +133,37 @@ public static void UpdateBackground(this FrameworkElement platformView, IView vi public static void UpdateFlowDirection(this FrameworkElement platformView, IView view) { - var flowDirection = view.FlowDirection; - switch (flowDirection) + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || view.FlowDirection != FlowDirection.MatchParent; + + if (skipInitialization != true) { - case FlowDirection.MatchParent: - platformView.ClearValue(FrameworkElement.FlowDirectionProperty); - break; - case FlowDirection.LeftToRight: - platformView.FlowDirection = WFlowDirection.LeftToRight; - break; - case FlowDirection.RightToLeft: - platformView.FlowDirection = WFlowDirection.RightToLeft; - break; + var flowDirection = view.FlowDirection; + switch (flowDirection) + { + case FlowDirection.MatchParent: + platformView.ClearValue(FrameworkElement.FlowDirectionProperty); + break; + case FlowDirection.LeftToRight: + platformView.FlowDirection = WFlowDirection.LeftToRight; + break; + case FlowDirection.RightToLeft: + platformView.FlowDirection = WFlowDirection.RightToLeft; + break; + } } } - public static void UpdateAutomationId(this FrameworkElement platformView, IView view) => - AutomationProperties.SetAutomationId(platformView, view.AutomationId); + public static void UpdateAutomationId(this FrameworkElement platformView, IView view) + { + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || view.AutomationId is not null; + + if (skipInitialization != true) + { + AutomationProperties.SetAutomationId(platformView, view.AutomationId); + } + } public static void UpdateSemantics(this FrameworkElement platformView, IView view) { @@ -179,16 +204,28 @@ public static void InvalidateMeasure(this FrameworkElement platformView, IView v public static void UpdateWidth(this FrameworkElement platformView, IView view) { - // WinUI uses NaN for "unspecified", so as long as we're using NaN for unspecified on the xplat side, - // we can just propagate the value straight through - platformView.Width = view.Width; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !double.IsNaN(view.Width); + + if (skipInitialization != true) + { + // WinUI uses NaN for "unspecified", so as long as we're using NaN for unspecified on the xplat side, + // we can just propagate the value straight through + platformView.Width = view.Width; + } } public static void UpdateHeight(this FrameworkElement platformView, IView view) { - // WinUI uses NaN for "unspecified", so as long as we're using NaN for unspecified on the xplat side, - // we can just propagate the value straight through - platformView.Height = view.Height; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !double.IsNaN(view.Height); + + if (skipInitialization != true) + { + // WinUI uses NaN for "unspecified", so as long as we're using NaN for unspecified on the xplat side, + // we can just propagate the value straight through + platformView.Height = view.Height; + } } public static void UpdateMinimumHeight(this FrameworkElement platformView, IView view) @@ -211,7 +248,10 @@ public static void UpdateMinimumWidth(this FrameworkElement platformView, IView { var minWidth = view.MinimumWidth; - if (Dimension.IsMinimumSet(minWidth)) + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || Dimension.IsMinimumSet(minWidth); + + if (skipInitialization != true) { // We only use the minimum value if it's been explicitly set; otherwise, clear the local // value so that the platform/theme can use the default minimum width for this control @@ -225,12 +265,24 @@ public static void UpdateMinimumWidth(this FrameworkElement platformView, IView public static void UpdateMaximumHeight(this FrameworkElement platformView, IView view) { - platformView.MaxHeight = view.MaximumHeight; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !Dimension.IsMaximumSet(view.MaximumHeight); + + if (skipInitialization != true) + { + platformView.MaxHeight = view.MaximumHeight; + } } public static void UpdateMaximumWidth(this FrameworkElement platformView, IView view) { - platformView.MaxWidth = view.MaximumWidth; + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !Dimension.IsMaximumSet(view.MaximumWidth); + + if (skipInitialization != true) + { + platformView.MaxWidth = view.MaximumWidth; + } } internal static void UpdateBorderBackground(this FrameworkElement platformView, IBorderStroke border) @@ -418,9 +470,15 @@ internal static void UnfocusControl(Control control) public static void UpdateInputTransparent(this FrameworkElement nativeView, IViewHandler handler, IView view) { - if (nativeView is UIElement element) + bool? skipInitialization = (view.Handler as ElementHandler)?._isPlatformViewNew ?? false + || !view.InputTransparent; + + if (skipInitialization != true) { - element.IsHitTestVisible = !view.InputTransparent; + if (nativeView is UIElement element) + { + element.IsHitTestVisible = !view.InputTransparent; + } } }