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