diff --git a/src/Controls/src/Core/Window/Window.cs b/src/Controls/src/Core/Window/Window.cs index 5bf70b1ea968..f99d478832c4 100644 --- a/src/Controls/src/Core/Window/Window.cs +++ b/src/Controls/src/Core/Window/Window.cs @@ -210,15 +210,24 @@ public double MinimumHeight void IWindow.FrameChanged(Rect frame) { - if (new Rect(X, Y, Width, Height) == frame) + var x = X; + var y = Y; + var width = Width; + var height = Height; + if (new Rect(x, y, width, height) == frame) return; _batchFrameUpdate++; - X = frame.X; - Y = frame.Y; - Width = frame.Width; - Height = frame.Height; + SetPropertyChanging(XProperty, nameof(X), x, frame.X); + SetPropertyChanging(YProperty, nameof(Y), y, frame.Y); + SetPropertyChanging(WidthProperty, nameof(Width), width, frame.Width); + SetPropertyChanging(HeightProperty, nameof(Height), height, frame.Height); + + SetValueCore(XProperty, frame.X, SetValueFlags.None, SetValuePrivateFlags.Silent); + SetValueCore(YProperty, frame.Y, SetValueFlags.None, SetValuePrivateFlags.Silent); + SetValueCore(WidthProperty, frame.Width, SetValueFlags.None, SetValuePrivateFlags.Silent); + SetValueCore(HeightProperty, frame.Height, SetValueFlags.None, SetValuePrivateFlags.Silent); _batchFrameUpdate--; if (_batchFrameUpdate < 0) @@ -226,8 +235,33 @@ void IWindow.FrameChanged(Rect frame) if (_batchFrameUpdate == 0) { + SetPropertyChanged(XProperty, nameof(X), x, frame.X); + SetPropertyChanged(YProperty, nameof(Y), y, frame.Y); + SetPropertyChanged(WidthProperty, nameof(Width), width, frame.Width); + SetPropertyChanged(HeightProperty, nameof(Height), height, frame.Height); + SizeChanged?.Invoke(this, EventArgs.Empty); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SetPropertyChanging(BindableProperty property, string name, double oldValue, double newValue) + { + if (oldValue == newValue) + return; + + property.PropertyChanging?.Invoke(this, oldValue, newValue); + OnPropertyChanging(name); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void SetPropertyChanged(BindableProperty property, string name, double oldValue, double newValue) + { + if (oldValue == newValue) + return; + + OnPropertyChanged(name); + property.PropertyChanged?.Invoke(this, oldValue, newValue); + } } public event EventHandler? ModalPopped; diff --git a/src/Controls/tests/Core.UnitTests/WindowsTests.cs b/src/Controls/tests/Core.UnitTests/WindowsTests.cs index f45d5fb2d14f..6f4f62d3876c 100644 --- a/src/Controls/tests/Core.UnitTests/WindowsTests.cs +++ b/src/Controls/tests/Core.UnitTests/WindowsTests.cs @@ -434,70 +434,82 @@ void ValidateSetup(Application app, Page page = null) public void SettingCoreFrameOnlyFiresEventOnce() { var sizeChangedCount = 0; - var propertyChanges = new List(); + var changingProperties = new List(); + var changedProperties = new List(); var window = new TestWindow(); window.SizeChanged += (sender, e) => sizeChangedCount++; - window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName); + window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName); + window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName); ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); Assert.Equal(1, sizeChangedCount); - Assert.Equal(new[] { "X", "Y", "Width", "Height" }, propertyChanges); + Assert.Equal(new[] { "X", "Y", "Width", "Height" }, changingProperties); + Assert.Equal(new[] { "X", "Y", "Width", "Height" }, changedProperties); } [Fact] public void SettingSameCoreFrameDoesNothing() { var sizeChangedCount = 0; - var propertyChanges = new List(); + var changingProperties = new List(); + var changedProperties = new List(); var window = new TestWindow(); ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); window.SizeChanged += (sender, e) => sizeChangedCount++; - window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName); + window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName); + window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName); ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); Assert.Equal(0, sizeChangedCount); - Assert.Empty(propertyChanges); + Assert.Empty(changingProperties); + Assert.Empty(changedProperties); } [Fact] public void UpdatingSingleCoordinateOnlyFiresSinglePropertyAndFrameEvent() { var sizeChangedCount = 0; - var propertyChanges = new List(); + var changingProperties = new List(); + var changedProperties = new List(); var window = new TestWindow(); ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); window.SizeChanged += (sender, e) => sizeChangedCount++; - window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName); + window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName); + window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName); ((IWindow)window).FrameChanged(new Rect(100, 250, 300, 400)); Assert.Equal(1, sizeChangedCount); - Assert.Equal(new[] { "Y" }, propertyChanges); + Assert.Equal(new[] { "Y" }, changingProperties); + Assert.Equal(new[] { "Y" }, changedProperties); } [Fact] public void UpdatingSingleBoundOnlyFiresSingleProperty() { var sizeChangedCount = 0; - var propertyChanges = new List(); + var changingProperties = new List(); + var changedProperties = new List(); var window = new TestWindow(); ((IWindow)window).FrameChanged(new Rect(100, 200, 300, 400)); window.SizeChanged += (sender, e) => sizeChangedCount++; - window.PropertyChanged += (sender, e) => propertyChanges.Add(e.PropertyName); + window.PropertyChanging += (sender, e) => changingProperties.Add(e.PropertyName); + window.PropertyChanged += (sender, e) => changedProperties.Add(e.PropertyName); ((IWindow)window).FrameChanged(new Rect(100, 200, 350, 400)); Assert.Equal(1, sizeChangedCount); - Assert.Equal(new[] { "Width" }, propertyChanges); + Assert.Equal(new[] { "Width" }, changingProperties); + Assert.Equal(new[] { "Width" }, changedProperties); } [Fact]