From eb6750822c75fb4e1be85c154515c70b4c3377c4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 10:23:35 +0000 Subject: [PATCH 01/10] Fix ClassicDesktop Lifetime so that ShutdownRequested event is raised even with programatic calls to Shutdown. --- .../ClassicDesktopStyleApplicationLifetime.cs | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index 3a2fd68af5..536e39cc34 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -83,29 +83,9 @@ namespace Avalonia.Controls.ApplicationLifetimes public void Shutdown(int exitCode = 0) { - if (_isShuttingDown) - throw new InvalidOperationException("Application is already shutting down."); - - _exitCode = exitCode; - _isShuttingDown = true; - - try - { - foreach (var w in Windows) - w.Close(); - var e = new ControlledApplicationLifetimeExitEventArgs(exitCode); - Exit?.Invoke(this, e); - _exitCode = e.ApplicationExitCode; - } - finally - { - _cts?.Cancel(); - _cts = null; - _isShuttingDown = false; - } + DoShutdown(new ShutdownRequestedEventArgs(), exitCode); } - public int Start(string[] args) { Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args)); @@ -145,23 +125,52 @@ namespace Avalonia.Controls.ApplicationLifetimes if (_activeLifetime == this) _activeLifetime = null; } - - private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) + + private void DoShutdown(ShutdownRequestedEventArgs e, int exitCode = 0) { ShutdownRequested?.Invoke(this, e); if (e.Cancel) return; - // When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel - // shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their - // owners. - foreach (var w in Windows) - if (w.Owner is null) - w.Close(); - if (Windows.Count > 0) - e.Cancel = true; + if (_isShuttingDown) + throw new InvalidOperationException("Application is already shutting down."); + + _exitCode = exitCode; + _isShuttingDown = true; + + try + { + // When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel + // shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their + // owners. + foreach (var w in Windows) + { + if (w.Owner is null) + { + w.Close(); + } + } + + if (Windows.Count > 0) + { + e.Cancel = true; + return; + } + + var e = new ControlledApplicationLifetimeExitEventArgs(exitCode); + Exit?.Invoke(this, e); + _exitCode = e.ApplicationExitCode; + } + finally + { + _cts?.Cancel(); + _cts = null; + _isShuttingDown = false; + } } + + private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e); } public class ClassicDesktopStyleApplicationLifetimeOptions From aeee9d165fb8e7414bfe1b21f261639ad7b01b2c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 10:35:07 +0000 Subject: [PATCH 02/10] add TryShutdown method. --- .../ClassicDesktopStyleApplicationLifetime.cs | 15 +++++++++++---- .../IClassicDesktopStyleApplicationLifetime.cs | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index 536e39cc34..8006149ee9 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -83,7 +83,12 @@ namespace Avalonia.Controls.ApplicationLifetimes public void Shutdown(int exitCode = 0) { - DoShutdown(new ShutdownRequestedEventArgs(), exitCode); + DoShutdown(new ShutdownRequestedEventArgs(), true, exitCode); + } + + public bool TryShutdown(int exitCode = 0) + { + return DoShutdown(new ShutdownRequestedEventArgs(), false, exitCode); } public int Start(string[] args) @@ -126,12 +131,12 @@ namespace Avalonia.Controls.ApplicationLifetimes _activeLifetime = null; } - private void DoShutdown(ShutdownRequestedEventArgs e, int exitCode = 0) + private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0) { ShutdownRequested?.Invoke(this, e); if (e.Cancel) - return; + false; if (_isShuttingDown) throw new InvalidOperationException("Application is already shutting down."); @@ -155,7 +160,7 @@ namespace Avalonia.Controls.ApplicationLifetimes if (Windows.Count > 0) { e.Cancel = true; - return; + return false; } var e = new ControlledApplicationLifetimeExitEventArgs(exitCode); @@ -168,6 +173,8 @@ namespace Avalonia.Controls.ApplicationLifetimes _cts = null; _isShuttingDown = false; } + + return true; } private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e); diff --git a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs index a70d5dd2f1..a83229b732 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs @@ -9,6 +9,12 @@ namespace Avalonia.Controls.ApplicationLifetimes /// public interface IClassicDesktopStyleApplicationLifetime : IControlledApplicationLifetime { + /// + /// Tries to Shutdown the application. event can be used to cancel the shutdown. + /// + /// An integer exit code for an application. The default exit code is 0. + bool TryShutdown(int exitCode = 0); + /// /// Gets the arguments passed to the /// From 15def96af4bca61bffd415cd4af76223f35d3c0f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 10:37:38 +0000 Subject: [PATCH 03/10] fix quit menu item osx. --- src/Avalonia.Native/AvaloniaNativeMenuExporter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index de6ba30a85..09d7247527 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs @@ -133,9 +133,9 @@ namespace Avalonia.Native var quitItem = new NativeMenuItem("Quit") { Gesture = new KeyGesture(Key.Q, KeyModifiers.Meta) }; quitItem.Click += (_, _) => { - if (Application.Current is { ApplicationLifetime: IControlledApplicationLifetime lifetime }) + if (Application.Current is { ApplicationLifetime: IClassicDesktopStyleApplicationLifetime lifetime }) { - lifetime.Shutdown(); + lifetime.TryShutdown(); } }; From 2a4a1b28b1a65315caf42d8fec5e0b6e85cf8246 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 10:38:11 +0000 Subject: [PATCH 04/10] add conditional force shutdown. --- src/Avalonia.Native/AvaloniaNativeMenuExporter.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index 09d7247527..67a27d5500 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs @@ -137,6 +137,10 @@ namespace Avalonia.Native { lifetime.TryShutdown(); } + else + { + lifetime.Shutdown(); + } }; appMenu.Add(quitItem); From aae3b701807b44398b1a2dff180c62af3eabd6f4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 12:02:01 +0000 Subject: [PATCH 05/10] fix build. --- src/Avalonia.Controls/ApiCompatBaseline.txt | 3 +- .../ClassicDesktopStyleApplicationLifetime.cs | 28 +++++++++++-------- .../AvaloniaNativeMenuExporter.cs | 4 +-- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt index 9b7d37e108..a7560c37f2 100644 --- a/src/Avalonia.Controls/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls/ApiCompatBaseline.txt @@ -36,6 +36,7 @@ CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not i InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.ShutdownRequested' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.add_ShutdownRequested(System.EventHandler)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.remove_ShutdownRequested(System.EventHandler)' is present in the implementation but not in the contract. +InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.TryShutdown(System.Int32)' is present in the implementation but not in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Embedding.EmbeddableControlRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber' in the implementation but it does in the contract. MembersMustExist : Member 'public System.Action Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.set(System.Action)' does not exist in the implementation but it does exist in the contract. @@ -62,4 +63,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract. -Total Issues: 63 +Total Issues: 64 diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index 8006149ee9..9d30c529fb 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -99,7 +99,10 @@ namespace Avalonia.Controls.ApplicationLifetimes if(options != null && options.ProcessUrlActivationCommandLine && args.Length > 0) { - ((IApplicationPlatformEvents)Application.Current).RaiseUrlsOpened(args); + if (Application.Current is IApplicationPlatformEvents events) + { + events.RaiseUrlsOpened(args); + } } var lifetimeEvents = AvaloniaLocator.Current.GetService(); @@ -133,14 +136,17 @@ namespace Avalonia.Controls.ApplicationLifetimes private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0) { - ShutdownRequested?.Invoke(this, e); + if (!force) + { + ShutdownRequested?.Invoke(this, e); + + if (e.Cancel) + return false; - if (e.Cancel) - false; + if (_isShuttingDown) + throw new InvalidOperationException("Application is already shutting down."); + } - if (_isShuttingDown) - throw new InvalidOperationException("Application is already shutting down."); - _exitCode = exitCode; _isShuttingDown = true; @@ -157,15 +163,15 @@ namespace Avalonia.Controls.ApplicationLifetimes } } - if (Windows.Count > 0) + if (!force && Windows.Count > 0) { e.Cancel = true; return false; } - var e = new ControlledApplicationLifetimeExitEventArgs(exitCode); - Exit?.Invoke(this, e); - _exitCode = e.ApplicationExitCode; + var args = new ControlledApplicationLifetimeExitEventArgs(exitCode); + Exit?.Invoke(this, args); + _exitCode = args.ApplicationExitCode; } finally { diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs index 67a27d5500..d8753efe25 100644 --- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs +++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs @@ -137,9 +137,9 @@ namespace Avalonia.Native { lifetime.TryShutdown(); } - else + else if(Application.Current is {ApplicationLifetime: IControlledApplicationLifetime controlledLifetime}) { - lifetime.Shutdown(); + controlledLifetime.Shutdown(); } }; From ed35eeeb69ef807628944624d4e6ede99620ddbc Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 12:06:59 +0000 Subject: [PATCH 06/10] allow MainWindow close mode and LastWindowClose mode to be cancellable. --- .../ClassicDesktopStyleApplicationLifetime.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs index 9d30c529fb..edddf31d45 100644 --- a/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs +++ b/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs @@ -76,9 +76,9 @@ namespace Avalonia.Controls.ApplicationLifetimes return; if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0) - Shutdown(); - else if (ShutdownMode == ShutdownMode.OnMainWindowClose && window == MainWindow) - Shutdown(); + TryShutdown(); + else if (ShutdownMode == ShutdownMode.OnMainWindowClose && ReferenceEquals(window, MainWindow)) + TryShutdown(); } public void Shutdown(int exitCode = 0) From 00c633ab3d01c1f7b270a42d3d8ac044fc30e29f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 12:20:04 +0000 Subject: [PATCH 07/10] Add a unit test to show we can now cancel window closing shutdown modes. --- .../DesktopStyleApplicationLifetimeTests.cs | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs index f7a3bdea1c..6c68ab0249 100644 --- a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Platform; -using Avalonia.Threading; using Avalonia.UnitTests; using Moq; using Xunit; @@ -238,5 +236,81 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(new[] { window }, lifetime.Windows); } } + + [Fact] + public void MainWindow_Closed_Shutdown_Should_Be_Cancellable() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) + { + lifetime.ShutdownMode = ShutdownMode.OnMainWindowClose; + + var hasExit = false; + + lifetime.Exit += (s, e) => hasExit = true; + + var mainWindow = new Window(); + + mainWindow.Show(); + + lifetime.MainWindow = mainWindow; + + var window = new Window(); + + window.Show(); + + var raised = 0; + + lifetime.ShutdownRequested += (s, e) => + { + e.Cancel = true; + ++raised; + }; + + mainWindow.Close(); + + Assert.Equal(1, raised); + Assert.False(hasExit); + } + } + + [Fact] + public void LastWindow_Closed_Shutdown_Should_Be_Cancellable() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) + { + lifetime.ShutdownMode = ShutdownMode.OnLastWindowClose; + + var hasExit = false; + + lifetime.Exit += (s, e) => hasExit = true; + + var windowA = new Window(); + + windowA.Show(); + + var windowB = new Window(); + + windowB.Show(); + + var raised = 0; + + lifetime.ShutdownRequested += (s, e) => + { + e.Cancel = true; + ++raised; + }; + + windowA.Close(); + + Assert.False(hasExit); + + windowB.Close(); + + Assert.Equal(1, raised); + Assert.False(hasExit); + } + } } } From 79fdf5ee5f70f08def6007ec303900d03bbef160 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 12:31:46 +0000 Subject: [PATCH 08/10] Add another unit test to show that windows can cancel the shutdown. --- .../DesktopStyleApplicationLifetimeTests.cs | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs index 6c68ab0249..4d7a640420 100644 --- a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs @@ -312,5 +312,38 @@ namespace Avalonia.Controls.UnitTests Assert.False(hasExit); } } + + [Fact] + public void TryShutdown_Cancellable_By_Preventing_Window_Close() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) + { + var hasExit = false; + + lifetime.Exit += (s, e) => hasExit = true; + + var windowA = new Window(); + + windowA.Show(); + + var windowB = new Window(); + + windowB.Show(); + + var raised = 0; + + windowA.Closing += (sender, e) => + { + e.Cancel = true; + ++raised; + }; + + lifetime.TryShutdown(); + + Assert.Equal(1, raised); + Assert.False(hasExit); + } + } } } From 262f520335b0a5107cd09bcf597b7e419eca6be8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 12:37:20 +0000 Subject: [PATCH 09/10] Add more unit tests. --- .../DesktopStyleApplicationLifetimeTests.cs | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs index 4d7a640420..470e24aea7 100644 --- a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs @@ -345,5 +345,62 @@ namespace Avalonia.Controls.UnitTests Assert.False(hasExit); } } + + [Fact] + public void Shutdown_NotCancellable_By_Preventing_Window_Close() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) + { + var hasExit = false; + + lifetime.Exit += (s, e) => hasExit = true; + + var windowA = new Window(); + + windowA.Show(); + + var windowB = new Window(); + + windowB.Show(); + + var raised = 0; + + windowA.Closing += (sender, e) => + { + e.Cancel = true; + ++raised; + }; + + lifetime.Shutdown(); + + Assert.Equal(1, raised); + Assert.True(hasExit); + } + } + + [Fact] + public void Shutdown_Doesnt_Raise_Shutdown_Requested() + { + using (UnitTestApplication.Start(TestServices.StyledWindow)) + using(var lifetime = new ClassicDesktopStyleApplicationLifetime()) + { + var hasExit = false; + + lifetime.Exit += (s, e) => hasExit = true; + + var raised = 0; + + lifetime.ShutdownRequested += (sender, e) => + { + ++raised; + }; + + lifetime.Shutdown(); + + Assert.Equal(0, raised); + Assert.True(hasExit); + } + } } } From 245d23e741b71bd5b0d44a4c37af652af60f50d8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 20 Jan 2022 13:09:50 +0000 Subject: [PATCH 10/10] use discards where possible. --- .../DesktopStyleApplicationLifetimeTests.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs index 470e24aea7..3a2e1c08bd 100644 --- a/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs +++ b/tests/Avalonia.Controls.UnitTests/DesktopStyleApplicationLifetimeTests.cs @@ -55,7 +55,7 @@ namespace Avalonia.Controls.UnitTests var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var windowA = new Window(); @@ -89,7 +89,7 @@ namespace Avalonia.Controls.UnitTests var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var mainWindow = new Window(); @@ -117,7 +117,7 @@ namespace Avalonia.Controls.UnitTests var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var windowA = new Window(); @@ -224,7 +224,7 @@ namespace Avalonia.Controls.UnitTests window.Show(); - lifetime.ShutdownRequested += (s, e) => + lifetime.ShutdownRequested += (_, e) => { e.Cancel = true; ++raised; @@ -247,7 +247,7 @@ namespace Avalonia.Controls.UnitTests var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var mainWindow = new Window(); @@ -261,7 +261,7 @@ namespace Avalonia.Controls.UnitTests var raised = 0; - lifetime.ShutdownRequested += (s, e) => + lifetime.ShutdownRequested += (_, e) => { e.Cancel = true; ++raised; @@ -284,7 +284,7 @@ namespace Avalonia.Controls.UnitTests var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var windowA = new Window(); @@ -296,7 +296,7 @@ namespace Avalonia.Controls.UnitTests var raised = 0; - lifetime.ShutdownRequested += (s, e) => + lifetime.ShutdownRequested += (_, e) => { e.Cancel = true; ++raised; @@ -321,7 +321,7 @@ namespace Avalonia.Controls.UnitTests { var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var windowA = new Window(); @@ -333,7 +333,7 @@ namespace Avalonia.Controls.UnitTests var raised = 0; - windowA.Closing += (sender, e) => + windowA.Closing += (_, e) => { e.Cancel = true; ++raised; @@ -354,7 +354,7 @@ namespace Avalonia.Controls.UnitTests { var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var windowA = new Window(); @@ -366,7 +366,7 @@ namespace Avalonia.Controls.UnitTests var raised = 0; - windowA.Closing += (sender, e) => + windowA.Closing += (_, e) => { e.Cancel = true; ++raised; @@ -387,11 +387,11 @@ namespace Avalonia.Controls.UnitTests { var hasExit = false; - lifetime.Exit += (s, e) => hasExit = true; + lifetime.Exit += (_, _) => hasExit = true; var raised = 0; - lifetime.ShutdownRequested += (sender, e) => + lifetime.ShutdownRequested += (_, _) => { ++raised; };