From 81846e87ece5f0a6c5e7a9146a46a941fdf79a29 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 24 Jan 2019 19:11:39 +0100 Subject: [PATCH 1/5] Added TopLevel.Opened event. And raise the event when a window is opened. --- src/Avalonia.Controls/TopLevel.cs | 11 +++++++++++ src/Avalonia.Controls/Window.cs | 2 ++ src/Avalonia.Controls/WindowBase.cs | 3 ++- 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 5ca3647da7..32c40847c5 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -136,6 +136,11 @@ namespace Avalonia.Controls } } + /// + /// Fired when the window is opened. + /// + public event EventHandler Opened; + /// /// Fired when the window is closed. /// @@ -311,6 +316,12 @@ namespace Avalonia.Controls $"Control '{GetType().Name}' is a top level control and cannot be added as a child."); } + /// + /// Raises the event. + /// + /// The event args. + protected virtual void OnOpened(EventArgs e) => Opened?.Invoke(this, e); + /// /// Tries to get a service from an , logging a /// warning if not found. diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 53f727900b..f5af6774b5 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -389,6 +389,7 @@ namespace Avalonia.Controls Renderer?.Start(); } SetWindowStartupLocation(Owner?.PlatformImpl); + OnOpened(EventArgs.Empty); } /// @@ -458,6 +459,7 @@ namespace Avalonia.Controls owner.Activate(); result.SetResult((TResult)(_dialogResult ?? default(TResult))); }); + OnOpened(EventArgs.Empty); } SetWindowStartupLocation(owner); diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 2fba8619c6..56ffd315f1 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -163,7 +163,7 @@ namespace Avalonia.Controls } /// - /// Shows the popup. + /// Shows the window. /// public virtual void Show() { @@ -181,6 +181,7 @@ namespace Avalonia.Controls } PlatformImpl?.Show(); Renderer?.Start(); + OnOpened(EventArgs.Empty); } finally { From 6a167a688271e37b0e3c5ce34655dc3699ccc8bc Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 24 Jan 2019 19:11:57 +0100 Subject: [PATCH 2/5] Use Window.Opened event for rxui activation. --- src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs b/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs index cf386a235e..e1db604e95 100644 --- a/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs +++ b/src/Avalonia.ReactiveUI/AvaloniaActivationForViewFetcher.cs @@ -29,8 +29,8 @@ namespace Avalonia { var windowLoaded = Observable .FromEventPattern( - x => window.Initialized += x, - x => window.Initialized -= x) + x => window.Opened += x, + x => window.Opened -= x) .Select(args => true); var windowUnloaded = Observable .FromEventPattern( @@ -59,4 +59,4 @@ namespace Avalonia .DistinctUntilChanged(); } } -} \ No newline at end of file +} From 068acb63769a2a8636715d7a2a4396b93d19db8c Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 24 Jan 2019 19:18:12 +0100 Subject: [PATCH 3/5] Added TopLevel.Opened unit tests. --- .../WindowBaseTests.cs | 16 ++++++++++++++ .../WindowTests.cs | 21 +++++++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs b/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs index 51a4d21392..6d00409ae0 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowBaseTests.cs @@ -199,6 +199,22 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Showing_Should_Raise_Opened() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var target = new TestWindowBase(); + var raised = false; + + target.Opened += (s, e) => raised = true; + + target.Show(); + + Assert.True(raised); + } + } + [Fact] public void Hiding_Should_Stop_Renderer() { diff --git a/tests/Avalonia.Controls.UnitTests/WindowTests.cs b/tests/Avalonia.Controls.UnitTests/WindowTests.cs index c0b5342934..8221dadc86 100644 --- a/tests/Avalonia.Controls.UnitTests/WindowTests.cs +++ b/tests/Avalonia.Controls.UnitTests/WindowTests.cs @@ -228,18 +228,35 @@ namespace Avalonia.Controls.UnitTests [Fact] public void ShowDialog_Should_Start_Renderer() { - using (UnitTestApplication.Start(TestServices.StyledWindow)) { + var parent = Mock.Of(); var renderer = new Mock(); var target = new Window(CreateImpl(renderer)); - target.Show(); + target.ShowDialog(parent); renderer.Verify(x => x.Start(), Times.Once); } } + [Fact] + public void ShowDialog_Should_Raise_Opened() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + { + var parent = Mock.Of(); + var target = new Window(); + var raised = false; + + target.Opened += (s, e) => raised = true; + + target.ShowDialog(parent); + + Assert.True(raised); + } + } + [Fact] public void Hiding_Should_Stop_Renderer() { From 163abb8322baa55741a00a477422e0b21879208a Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 25 Jan 2019 12:54:29 +0100 Subject: [PATCH 4/5] Added Avalonia.ReactiveUI.UnitTests to solution. --- Avalonia.sln | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/Avalonia.sln b/Avalonia.sln index 2f7560049c..d6472503fe 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -196,9 +196,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_build", "nukebuild\_build. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Animation.UnitTests", "tests\Avalonia.Animation.UnitTests\Avalonia.Animation.UnitTests.csproj", "{AF227847-E65C-4BE9-BCE9-B551357788E0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.X11", "src\Avalonia.X11\Avalonia.X11.csproj", "{41B02319-965D-4945-8005-C1A3D1224165}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PlatformSanityChecks", "samples\PlatformSanityChecks\PlatformSanityChecks.csproj", "{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI.UnitTests", "tests\Avalonia.ReactiveUI.UnitTests\Avalonia.ReactiveUI.UnitTests.csproj", "{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}" EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution @@ -1819,6 +1821,30 @@ Global {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhone.Build.0 = Release|Any CPU {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhone.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhone.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|Any CPU.Build.0 = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.ActiveCfg = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhone.Build.0 = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1875,6 +1901,7 @@ Global {AF227847-E65C-4BE9-BCE9-B551357788E0} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098} + {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} From 653fa458c16d8734b6d918c14a9e810bad76e026 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 25 Jan 2019 12:55:16 +0100 Subject: [PATCH 5/5] Call InitializeComponent in RxUI activation tests. To make sure activation works after loading XAML. --- .../AvaloniaActivationForViewFetcherTest.cs | 35 +++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs index b782311729..70a5504a7d 100644 --- a/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs +++ b/tests/Avalonia.ReactiveUI.UnitTests/AvaloniaActivationForViewFetcherTest.cs @@ -10,6 +10,7 @@ using ReactiveUI; using DynamicData; using Xunit; using Splat; +using Avalonia.Markup.Xaml; namespace Avalonia { @@ -70,12 +71,40 @@ namespace Avalonia public class ActivatableWindow : ReactiveWindow { - public ActivatableWindow() => this.WhenActivated(disposables => { }); + public ActivatableWindow() + { + InitializeComponent(); + Assert.IsType(Content); + this.WhenActivated(disposables => { }); + } + + private void InitializeComponent() + { + var loader = new AvaloniaXamlLoader(); + loader.Load(@" + + +", null, this); + } } public class ActivatableUserControl : ReactiveUserControl { - public ActivatableUserControl() => this.WhenActivated(disposables => { }); + public ActivatableUserControl() + { + InitializeComponent(); + Assert.IsType(Content); + this.WhenActivated(disposables => { }); + } + + private void InitializeComponent() + { + var loader = new AvaloniaXamlLoader(); + loader.Load(@" + + +", null, this); + } } public AvaloniaActivationForViewFetcherTest() @@ -183,4 +212,4 @@ namespace Avalonia Assert.False(viewModel.IsActivated); } } -} \ No newline at end of file +}