From f23bfafbaef806b380013ddd7a22a2da190bbf06 Mon Sep 17 00:00:00 2001 From: artyom Date: Mon, 10 Aug 2020 22:40:59 +0300 Subject: [PATCH 1/7] Show default content when Router is null --- src/Avalonia.ReactiveUI/RoutedViewHost.cs | 8 +++++ .../RoutedViewHostTest.cs | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/Avalonia.ReactiveUI/RoutedViewHost.cs b/src/Avalonia.ReactiveUI/RoutedViewHost.cs index 1af8012a20..5520121033 100644 --- a/src/Avalonia.ReactiveUI/RoutedViewHost.cs +++ b/src/Avalonia.ReactiveUI/RoutedViewHost.cs @@ -66,6 +66,7 @@ namespace Avalonia.ReactiveUI this.WhenActivated(disposables => { this.WhenAnyObservable(x => x.Router.CurrentViewModel) + .StartWith(default(object)) .DistinctUntilChanged() .Subscribe(NavigateToViewModel) .DisposeWith(disposables); @@ -92,6 +93,13 @@ namespace Avalonia.ReactiveUI /// ViewModel to which the user navigates. private void NavigateToViewModel(object viewModel) { + if (Router == null) + { + this.Log().Warn("Router property is null. Falling back to default content."); + Content = DefaultContent; + return; + } + if (viewModel == null) { this.Log().Info("ViewModel is null. Falling back to default content."); diff --git a/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs index f4d9222085..5b7f7fe336 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs @@ -108,5 +108,39 @@ namespace Avalonia.ReactiveUI.UnitTests Assert.Equal(typeof(TextBlock), host.Content.GetType()); Assert.Equal(defaultContent, host.Content); } + + [Fact] + public void RoutedViewHost_Should_Show_Default_Content_When_Router_Is_Null() + { + var screen = new ScreenViewModel(); + var defaultContent = new TextBlock(); + var host = new RoutedViewHost + { + DefaultContent = defaultContent, + PageTransition = null, + Router = null + }; + + var root = new TestRoot + { + Child = host + }; + + Assert.NotNull(host.Content); + Assert.Equal(defaultContent, host.Content); + + host.Router = screen.Router; + + Assert.NotNull(host.Content); + Assert.Equal(defaultContent, host.Content); + + var first = new FirstRoutableViewModel(); + screen.Router.Navigate.Execute(first).Subscribe(); + + Assert.NotNull(host.Content); + Assert.Equal(typeof(FirstRoutableView), host.Content.GetType()); + Assert.Equal(first, ((FirstRoutableView)host.Content).DataContext); + Assert.Equal(first, ((FirstRoutableView)host.Content).ViewModel); + } } } \ No newline at end of file From b2b7fafabfc211cf37f227dc263ec40f20adeafe Mon Sep 17 00:00:00 2001 From: artyom Date: Mon, 10 Aug 2020 23:41:09 +0300 Subject: [PATCH 2/7] Bring additional tests for binding hooks --- .../AutoDataTemplateBindingHookTest.cs | 64 ++++++++++++++++--- 1 file changed, 54 insertions(+), 10 deletions(-) diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs index 8ef37dbd21..2fdd12a391 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs @@ -28,11 +28,36 @@ namespace Avalonia.ReactiveUI.UnitTests public class ExampleView : ReactiveUserControl { - public ItemsControl List { get; } = new ItemsControl(); + public ItemsControl List { get; } = new ItemsControl + { + Template = GetTemplate() + }; public ExampleView() { + List.ApplyTemplate(); + List.Presenter.ApplyTemplate(); Content = List; + + ViewModel = new ExampleViewModel(); + this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items); + } + } + + public class ExampleViewWithItemTemplate : ReactiveUserControl + { + public ItemsControl List { get; } = new ItemsControl + { + Template = GetTemplate() + }; + + public ExampleViewWithItemTemplate() + { + List.ApplyTemplate(); + List.Presenter.ApplyTemplate(); + List.ItemTemplate = GetItemTemplate(); + Content = List; + ViewModel = new ExampleViewModel(); this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items); } @@ -50,6 +75,15 @@ namespace Avalonia.ReactiveUI.UnitTests { var view = new ExampleView(); Assert.NotNull(view.List.ItemTemplate); + Assert.IsType>(view.List.ItemTemplate); + } + + [Fact] + public void Should_Not_Override_Data_Template_Binding_When_Item_Template_Is_Set() + { + var view = new ExampleViewWithItemTemplate(); + Assert.NotNull(view.List.ItemTemplate); + Assert.IsType>(view.List.ItemTemplate); } [Fact] @@ -58,10 +92,6 @@ namespace Avalonia.ReactiveUI.UnitTests var view = new ExampleView(); view.ViewModel.Items.Add(new NestedViewModel()); - view.List.Template = GetTemplate(); - view.List.ApplyTemplate(); - view.List.Presenter.ApplyTemplate(); - var child = view.List.Presenter.Panel.Children[0]; var container = (ContentPresenter) child; container.UpdateChild(); @@ -69,6 +99,19 @@ namespace Avalonia.ReactiveUI.UnitTests Assert.IsType(container.Child); } + [Fact] + public void Should_Not_Use_View_Model_View_Host_When_Item_Template_Is_Set() + { + var view = new ExampleViewWithItemTemplate(); + view.ViewModel.Items.Add(new NestedViewModel()); + + var child = view.List.Presenter.Panel.Children[0]; + var container = (ContentPresenter) child; + container.UpdateChild(); + + Assert.IsType(container.Child); + } + [Fact] public void Should_Resolve_And_Embedd_Appropriate_View_Model() { @@ -76,10 +119,6 @@ namespace Avalonia.ReactiveUI.UnitTests var root = new TestRoot { Child = view }; view.ViewModel.Items.Add(new NestedViewModel()); - view.List.Template = GetTemplate(); - view.List.ApplyTemplate(); - view.List.Presenter.ApplyTemplate(); - var child = view.List.Presenter.Panel.Children[0]; var container = (ContentPresenter) child; container.UpdateChild(); @@ -93,7 +132,12 @@ namespace Avalonia.ReactiveUI.UnitTests Assert.IsType(host.DataContext); } - private FuncControlTemplate GetTemplate() + private static FuncDataTemplate GetItemTemplate() + { + return new FuncDataTemplate((parent, scope) => new TextBlock()); + } + + private static FuncControlTemplate GetTemplate() { return new FuncControlTemplate((parent, scope) => { From fbc549b51cfa62a45de0f5171dd9e9ada70e54b1 Mon Sep 17 00:00:00 2001 From: artyom Date: Mon, 10 Aug 2020 23:57:46 +0300 Subject: [PATCH 3/7] Don't apply hook when DataTemplates property is set --- .../AutoDataTemplateBindingHook.cs | 4 ++ .../AutoDataTemplateBindingHookTest.cs | 57 ++++++++----------- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs b/src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs index 4881c77034..fe4e9dd94a 100644 --- a/src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs +++ b/src/Avalonia.ReactiveUI/AutoDataTemplateBindingHook.cs @@ -48,6 +48,10 @@ namespace Avalonia.ReactiveUI if (itemsControl.ItemTemplate != null) return true; + if (itemsControl.DataTemplates != null && + itemsControl.DataTemplates.Count > 0) + return true; + itemsControl.ItemTemplate = DefaultItemTemplate; return true; } diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs index 2fdd12a391..0a04d802e2 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs @@ -33,31 +33,13 @@ namespace Avalonia.ReactiveUI.UnitTests Template = GetTemplate() }; - public ExampleView() + public ExampleView(Action adjustItemsControl = null) { + adjustItemsControl?.Invoke(List); List.ApplyTemplate(); List.Presenter.ApplyTemplate(); + Content = List; - - ViewModel = new ExampleViewModel(); - this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items); - } - } - - public class ExampleViewWithItemTemplate : ReactiveUserControl - { - public ItemsControl List { get; } = new ItemsControl - { - Template = GetTemplate() - }; - - public ExampleViewWithItemTemplate() - { - List.ApplyTemplate(); - List.Presenter.ApplyTemplate(); - List.ItemTemplate = GetItemTemplate(); - Content = List; - ViewModel = new ExampleViewModel(); this.OneWayBind(ViewModel, x => x.Items, x => x.List.Items); } @@ -81,7 +63,7 @@ namespace Avalonia.ReactiveUI.UnitTests [Fact] public void Should_Not_Override_Data_Template_Binding_When_Item_Template_Is_Set() { - var view = new ExampleViewWithItemTemplate(); + var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); Assert.NotNull(view.List.ItemTemplate); Assert.IsType>(view.List.ItemTemplate); } @@ -102,7 +84,20 @@ namespace Avalonia.ReactiveUI.UnitTests [Fact] public void Should_Not_Use_View_Model_View_Host_When_Item_Template_Is_Set() { - var view = new ExampleViewWithItemTemplate(); + var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); + view.ViewModel.Items.Add(new NestedViewModel()); + + var child = view.List.Presenter.Panel.Children[0]; + var container = (ContentPresenter) child; + container.UpdateChild(); + + Assert.IsType(container.Child); + } + + [Fact] + public void Should_Not_Use_View_Model_View_Host_When_Data_Templates_Are_Not_Empty() + { + var view = new ExampleView(control => control.DataTemplates.Add(GetItemTemplate())); view.ViewModel.Items.Add(new NestedViewModel()); var child = view.List.Presenter.Panel.Children[0]; @@ -116,7 +111,6 @@ namespace Avalonia.ReactiveUI.UnitTests public void Should_Resolve_And_Embedd_Appropriate_View_Model() { var view = new ExampleView(); - var root = new TestRoot { Child = view }; view.ViewModel.Items.Add(new NestedViewModel()); var child = view.List.Presenter.Panel.Children[0]; @@ -139,17 +133,14 @@ namespace Avalonia.ReactiveUI.UnitTests private static FuncControlTemplate GetTemplate() { - return new FuncControlTemplate((parent, scope) => + return new FuncControlTemplate((parent, scope) => new Border { - return new Border + Background = new Media.SolidColorBrush(0xffffffff), + Child = new ItemsPresenter { - Background = new Media.SolidColorBrush(0xffffffff), - Child = new ItemsPresenter - { - Name = "PART_ItemsPresenter", - [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], - }.RegisterInNameScope(scope) - }; + Name = "PART_ItemsPresenter", + [~ItemsPresenter.ItemsProperty] = parent[~ItemsControl.ItemsProperty], + }.RegisterInNameScope(scope) }); } } From 0bbe03643744a9a1563da82e55a290fea4449a21 Mon Sep 17 00:00:00 2001 From: artyom Date: Tue, 11 Aug 2020 10:35:29 +0300 Subject: [PATCH 4/7] Show DefaultContent when Router is set to null --- src/Avalonia.ReactiveUI/RoutedViewHost.cs | 12 +++-- .../AutoDataTemplateBindingHookTest.cs | 50 ++++++++--------- .../RoutedViewHostTest.cs | 54 +++++++++---------- 3 files changed, 61 insertions(+), 55 deletions(-) diff --git a/src/Avalonia.ReactiveUI/RoutedViewHost.cs b/src/Avalonia.ReactiveUI/RoutedViewHost.cs index 5520121033..38100f4829 100644 --- a/src/Avalonia.ReactiveUI/RoutedViewHost.cs +++ b/src/Avalonia.ReactiveUI/RoutedViewHost.cs @@ -65,9 +65,15 @@ namespace Avalonia.ReactiveUI { this.WhenActivated(disposables => { - this.WhenAnyObservable(x => x.Router.CurrentViewModel) - .StartWith(default(object)) - .DistinctUntilChanged() + var routerRemoved = this + .WhenAnyValue(x => x.Router) + .Where(router => router == null) + .Cast(); + + this.WhenAnyValue(x => x.Router) + .Where(router => router != null) + .SelectMany(router => router.CurrentViewModel) + .Merge(routerRemoved) .Subscribe(NavigateToViewModel) .DisposeWith(disposables); }); diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs index 0a04d802e2..53bdff5dff 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AutoDataTemplateBindingHookTest.cs @@ -61,15 +61,7 @@ namespace Avalonia.ReactiveUI.UnitTests } [Fact] - public void Should_Not_Override_Data_Template_Binding_When_Item_Template_Is_Set() - { - var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); - Assert.NotNull(view.List.ItemTemplate); - Assert.IsType>(view.List.ItemTemplate); - } - - [Fact] - public void Should_Use_View_Model_View_Host_As_Data_Template() + public void Should_Use_ViewModelViewHost_As_Data_Template_By_Default() { var view = new ExampleView(); view.ViewModel.Items.Add(new NestedViewModel()); @@ -82,22 +74,36 @@ namespace Avalonia.ReactiveUI.UnitTests } [Fact] - public void Should_Not_Use_View_Model_View_Host_When_Item_Template_Is_Set() + public void ViewModelViewHost_Should_Resolve_And_Embedd_Appropriate_View_Model() { - var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); + var view = new ExampleView(); view.ViewModel.Items.Add(new NestedViewModel()); var child = view.List.Presenter.Panel.Children[0]; var container = (ContentPresenter) child; container.UpdateChild(); - Assert.IsType(container.Child); + var host = (ViewModelViewHost) container.Child; + Assert.IsType(host.ViewModel); + Assert.IsType(host.DataContext); + + host.DataContext = "changed context"; + Assert.IsType(host.ViewModel); + Assert.IsType(host.DataContext); } - + [Fact] - public void Should_Not_Use_View_Model_View_Host_When_Data_Templates_Are_Not_Empty() + public void Should_Not_Override_Data_Template_Binding_When_Item_Template_Is_Set() { - var view = new ExampleView(control => control.DataTemplates.Add(GetItemTemplate())); + var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); + Assert.NotNull(view.List.ItemTemplate); + Assert.IsType>(view.List.ItemTemplate); + } + + [Fact] + public void Should_Not_Use_View_Model_View_Host_When_Item_Template_Is_Set() + { + var view = new ExampleView(control => control.ItemTemplate = GetItemTemplate()); view.ViewModel.Items.Add(new NestedViewModel()); var child = view.List.Presenter.Panel.Children[0]; @@ -106,24 +112,18 @@ namespace Avalonia.ReactiveUI.UnitTests Assert.IsType(container.Child); } - + [Fact] - public void Should_Resolve_And_Embedd_Appropriate_View_Model() + public void Should_Not_Use_View_Model_View_Host_When_Data_Templates_Are_Not_Empty() { - var view = new ExampleView(); + var view = new ExampleView(control => control.DataTemplates.Add(GetItemTemplate())); view.ViewModel.Items.Add(new NestedViewModel()); var child = view.List.Presenter.Panel.Children[0]; var container = (ContentPresenter) child; container.UpdateChild(); - var host = (ViewModelViewHost) container.Child; - Assert.IsType(host.ViewModel); - Assert.IsType(host.DataContext); - - host.DataContext = "changed context"; - Assert.IsType(host.ViewModel); - Assert.IsType(host.DataContext); + Assert.IsType(container.Child); } private static FuncDataTemplate GetItemTemplate() diff --git a/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs index 5b7f7fe336..b82b1b1acc 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/RoutedViewHostTest.cs @@ -62,50 +62,42 @@ namespace Avalonia.ReactiveUI.UnitTests PageTransition = null }; - var root = new TestRoot - { - Child = host + var root = new TestRoot + { + Child = host }; Assert.NotNull(host.Content); - Assert.Equal(typeof(TextBlock), host.Content.GetType()); + Assert.IsType(host.Content); Assert.Equal(defaultContent, host.Content); var first = new FirstRoutableViewModel(); - screen.Router.Navigate - .Execute(first) - .Subscribe(); + screen.Router.Navigate.Execute(first).Subscribe(); Assert.NotNull(host.Content); - Assert.Equal(typeof(FirstRoutableView), host.Content.GetType()); + Assert.IsType(host.Content); Assert.Equal(first, ((FirstRoutableView)host.Content).DataContext); Assert.Equal(first, ((FirstRoutableView)host.Content).ViewModel); var second = new SecondRoutableViewModel(); - screen.Router.Navigate - .Execute(second) - .Subscribe(); + screen.Router.Navigate.Execute(second).Subscribe(); Assert.NotNull(host.Content); - Assert.Equal(typeof(SecondRoutableView), host.Content.GetType()); + Assert.IsType(host.Content); Assert.Equal(second, ((SecondRoutableView)host.Content).DataContext); Assert.Equal(second, ((SecondRoutableView)host.Content).ViewModel); - screen.Router.NavigateBack - .Execute(Unit.Default) - .Subscribe(); + screen.Router.NavigateBack.Execute(Unit.Default).Subscribe(); Assert.NotNull(host.Content); - Assert.Equal(typeof(FirstRoutableView), host.Content.GetType()); + Assert.IsType(host.Content); Assert.Equal(first, ((FirstRoutableView)host.Content).DataContext); Assert.Equal(first, ((FirstRoutableView)host.Content).ViewModel); - screen.Router.NavigateBack - .Execute(Unit.Default) - .Subscribe(); + screen.Router.NavigateBack.Execute(Unit.Default).Subscribe(); Assert.NotNull(host.Content); - Assert.Equal(typeof(TextBlock), host.Content.GetType()); + Assert.IsType(host.Content); Assert.Equal(defaultContent, host.Content); } @@ -121,9 +113,9 @@ namespace Avalonia.ReactiveUI.UnitTests Router = null }; - var root = new TestRoot - { - Child = host + var root = new TestRoot + { + Child = host }; Assert.NotNull(host.Content); @@ -138,9 +130,17 @@ namespace Avalonia.ReactiveUI.UnitTests screen.Router.Navigate.Execute(first).Subscribe(); Assert.NotNull(host.Content); - Assert.Equal(typeof(FirstRoutableView), host.Content.GetType()); - Assert.Equal(first, ((FirstRoutableView)host.Content).DataContext); - Assert.Equal(first, ((FirstRoutableView)host.Content).ViewModel); + Assert.IsType(host.Content); + + host.Router = null; + + Assert.NotNull(host.Content); + Assert.Equal(defaultContent, host.Content); + + host.Router = screen.Router; + + Assert.NotNull(host.Content); + Assert.IsType(host.Content); } } -} \ No newline at end of file +} From 64d11e2e316e4d4a402e26bb846aff1c6ee17e45 Mon Sep 17 00:00:00 2001 From: artyom Date: Tue, 11 Aug 2020 10:37:20 +0300 Subject: [PATCH 5/7] Cast the view to IDataContextProvider --- src/Avalonia.ReactiveUI/RoutedViewHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.ReactiveUI/RoutedViewHost.cs b/src/Avalonia.ReactiveUI/RoutedViewHost.cs index 38100f4829..421633cd58 100644 --- a/src/Avalonia.ReactiveUI/RoutedViewHost.cs +++ b/src/Avalonia.ReactiveUI/RoutedViewHost.cs @@ -124,8 +124,8 @@ namespace Avalonia.ReactiveUI this.Log().Info($"Ready to show {viewInstance} with autowired {viewModel}."); viewInstance.ViewModel = viewModel; - if (viewInstance is IStyledElement styled) - styled.DataContext = viewModel; + if (viewInstance is IDataContextProvider provider) + provider.DataContext = viewModel; Content = viewInstance; } } From d59a0f80fe09ce670d78a6a06a7bc674f8a45829 Mon Sep 17 00:00:00 2001 From: artyom Date: Tue, 11 Aug 2020 10:40:41 +0300 Subject: [PATCH 6/7] Use latest ReactiveUI --- build/ReactiveUI.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/ReactiveUI.props b/build/ReactiveUI.props index f827cb9a32..d8e86e917e 100644 --- a/build/ReactiveUI.props +++ b/build/ReactiveUI.props @@ -1,5 +1,5 @@ - + From 7a325af366cfe1c91d905ae41ef617415edb6d45 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 12 Aug 2020 20:52:08 +0200 Subject: [PATCH 7/7] Fix auto-sizing on secondary monitors on win32. - Allow nested calls to `BeginAutoSizing` - previously it was called twice when showing a window on a secondary monitor and when the second `using` block exited it cleared the autosizing state despite the outer block not completing - Call `SetWindowStartupLocation` within the auto-sizing block. Moving to a secondary monitor causes a resize message. --- src/Avalonia.Controls/Window.cs | 2 +- src/Avalonia.Controls/WindowBase.cs | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index d8e7f3a387..317b6d3f2e 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -652,8 +652,8 @@ namespace Avalonia.Controls PlatformImpl?.Show(); Renderer?.Start(); + SetWindowStartupLocation(Owner?.PlatformImpl); } - SetWindowStartupLocation(Owner?.PlatformImpl); OnOpened(EventArgs.Empty); } diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index eb6e7319f5..1efd6c8c1d 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -39,6 +39,7 @@ namespace Avalonia.Controls public static readonly StyledProperty TopmostProperty = AvaloniaProperty.Register(nameof(Topmost)); + private int _autoSizing; private bool _hasExecutedInitialLayoutPass; private bool _isActive; private bool _ignoreVisibilityChange; @@ -97,11 +98,7 @@ namespace Avalonia.Controls /// /// Whether an auto-size operation is in progress. /// - protected bool AutoSizing - { - get; - private set; - } + protected bool AutoSizing => _autoSizing > 0; /// /// Gets or sets the owner of the window. @@ -186,8 +183,8 @@ namespace Avalonia.Controls /// protected IDisposable BeginAutoSizing() { - AutoSizing = true; - return Disposable.Create(() => AutoSizing = false); + ++_autoSizing; + return Disposable.Create(() => --_autoSizing); } ///