diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 9c0015232793..3e871da11820 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -44,11 +44,13 @@ public partial class Window : NavigableElement, IWindow, IToolbarElement, IMenuB /// Bindable property for . public static readonly BindableProperty WidthProperty = BindableProperty.Create( - nameof(Width), typeof(double), typeof(Window), Primitives.Dimension.Unset); + nameof(Width), typeof(double), typeof(Window), Primitives.Dimension.Unset, + propertyChanged: OnSizePropertyChanged); /// Bindable property for . public static readonly BindableProperty HeightProperty = BindableProperty.Create( - nameof(Height), typeof(double), typeof(Window), Primitives.Dimension.Unset); + nameof(Height), typeof(double), typeof(Window), Primitives.Dimension.Unset, + propertyChanged: OnSizePropertyChanged); /// Bindable property for . public static readonly BindableProperty MaximumWidthProperty = BindableProperty.Create( @@ -228,6 +230,16 @@ double GetSizeCoordinate(BindableProperty property) int _batchFrameUpdate = 0; + static void OnSizePropertyChanged(BindableObject bindable, object oldValue, object newValue) + { + var window = (Window)bindable; + // Only trigger SizeChanged if not being updated from platform (FrameChanged) + if (window._batchFrameUpdate == 0) + { + window.SizeChanged?.Invoke(window, EventArgs.Empty); + } + } + void IWindow.FrameChanged(Rect frame) { if (new Rect(X, Y, Width, Height) == frame) diff --git a/src/Controls/tests/TestCases.HostApp/Issues/Issue27646.cs b/src/Controls/tests/TestCases.HostApp/Issues/Issue27646.cs new file mode 100644 index 000000000000..8f45e6f492c0 --- /dev/null +++ b/src/Controls/tests/TestCases.HostApp/Issues/Issue27646.cs @@ -0,0 +1,99 @@ +namespace Maui.Controls.Sample.Issues; + +[Issue(IssueTracker.Github, 27646, "AdaptiveTrigger not firing when changing window width programmatically only", PlatformAffected.UWP)] +public class Issue27646 : ContentPage +{ + Label indicatorLabel; + Label statusLabel; + + public Issue27646() + { + var stackLayout = new VerticalStackLayout + { + Padding = 20, + Spacing = 10 + }; + + var instructionLabel = new Label + { + Text = "Click button to resize window. Label text should change at 600px window width.", + AutomationId = "InstructionLabel" + }; + stackLayout.Add(instructionLabel); + + statusLabel = new Label + { + Text = "Window width: Unknown", + AutomationId = "StatusLabel", + FontAttributes = FontAttributes.Bold + }; + stackLayout.Add(statusLabel); + + var resizeButton = new Button + { + Text = "Resize Window", + AutomationId = "ResizeButton" + }; + resizeButton.Clicked += OnResizeClicked; + stackLayout.Add(resizeButton); + + indicatorLabel = new Label + { + Text = "Initial", + WidthRequest = 200, + HeightRequest = 100, + HorizontalTextAlignment = TextAlignment.Center, + VerticalTextAlignment = TextAlignment.Center, + AutomationId = "IndicatorLabel" + }; + stackLayout.Add(indicatorLabel); + + Content = stackLayout; + + VisualStateManager.SetVisualStateGroups(indicatorLabel, new VisualStateGroupList + { + new VisualStateGroup + { + Name = "WindowWidthStates", + States = + { + new VisualState + { + Name = "Narrow", + StateTriggers = + { + new AdaptiveTrigger { MinWindowWidth = 0 } + }, + Setters = + { + new Setter { Property = Label.TextProperty, Value = "Narrow Window" } + } + }, + new VisualState + { + Name = "Wide", + StateTriggers = + { + new AdaptiveTrigger { MinWindowWidth = 600 } + }, + Setters = + { + new Setter { Property = Label.TextProperty, Value = "Wide Window" } + } + } + } + } + }); + } + + void OnResizeClicked(object sender, EventArgs e) + { + if (Window is not null) + { + double newWidth = Window.Width >= 600 ? 550 : 650; + Window.Width = newWidth; + + statusLabel.Text = $"Window width: {newWidth}px"; + } + } +} diff --git a/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27646.cs b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27646.cs new file mode 100644 index 000000000000..adac85033c47 --- /dev/null +++ b/src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue27646.cs @@ -0,0 +1,33 @@ +#if WINDOWS // MacCatalyst don't support programmatic window resizing. So, ignored test on MacCatalyst. +using NUnit.Framework; +using UITest.Appium; +using UITest.Core; + +namespace Microsoft.Maui.TestCases.Tests.Issues; + +public class Issue27646 : _IssuesUITest +{ + public override string Issue => "AdaptiveTrigger not firing when changing window width programmatically only"; + + public Issue27646(TestDevice device) : base(device) { } + + [Test] + [Category(UITestCategories.Window)] + public void AdaptiveTriggerShouldFireWhenWindowWidthChangedProgrammatically() + { + App.WaitForElement("ResizeButton"); + + App.Tap("ResizeButton"); + + var indicatorAfterFirstClick = App.FindElement("IndicatorLabel"); + Assert.That(indicatorAfterFirstClick.GetText(), Is.EqualTo("Narrow Window"), + "Label should show 'Narrow Window' after resizing to 550px"); + + App.Tap("ResizeButton"); + + var indicatorAfterSecondClick = App.FindElement("IndicatorLabel"); + Assert.That(indicatorAfterSecondClick.GetText(), Is.EqualTo("Wide Window"), + "Label should show 'Wide Window' after resizing to 650px"); + } +} +#endif