diff --git a/DialogHost.Avalonia/DialogClosingEventArgs.cs b/DialogHost.Avalonia/DialogClosingEventArgs.cs
index 241ee0e..9f6f325 100644
--- a/DialogHost.Avalonia/DialogClosingEventArgs.cs
+++ b/DialogHost.Avalonia/DialogClosingEventArgs.cs
@@ -6,11 +6,25 @@ namespace DialogHostAvalonia;
///
/// Event args contains info about dialog closing
///
-public class DialogClosingEventArgs(DialogSession session, RoutedEvent routedEvent) : RoutedEventArgs(routedEvent) {
+public class DialogClosingEventArgs(DialogSession session, RoutedEvent routedEvent, bool canBeCancelled)
+ : RoutedEventArgs(routedEvent) {
+ ///
+ [Obsolete("Use constructor with canBeCancelled parameter")]
+ public DialogClosingEventArgs(DialogSession session, RoutedEvent routedEvent) : this(session, routedEvent, true) {
+ }
+
///
/// Cancel the close.
///
- public void Cancel() => IsCancelled = true;
+ public void Cancel() {
+ if (!CanBeCancelled) {
+ throw new InvalidOperationException(
+ $"Cannot cancel dialog closing after {nameof(DialogHost)}.{nameof(DialogHost.IsOpen)} " +
+ $"property has been set to {bool.FalseString}");
+ }
+
+ IsCancelled = true;
+ }
///
/// Indicates if the close has already been cancelled.
@@ -26,4 +40,12 @@ public class DialogClosingEventArgs(DialogSession session, RoutedEvent routedEve
/// Allows interaction with the current dialog session.
///
public DialogSession Session { get; } = session ?? throw new ArgumentNullException(nameof(session));
+
+ ///
+ /// Indicates if the close can be canceled.
+ ///
+ ///
+ /// Typically this is true unless closing is triggered by setting to false.
+ ///
+ public bool CanBeCancelled { get; } = canBeCancelled;
}
\ No newline at end of file
diff --git a/DialogHost.Avalonia/DialogHost.axaml.cs b/DialogHost.Avalonia/DialogHost.axaml.cs
index b278732..ac8d0be 100644
--- a/DialogHost.Avalonia/DialogHost.axaml.cs
+++ b/DialogHost.Avalonia/DialogHost.axaml.cs
@@ -687,11 +687,13 @@ private void IsOpenPropertyChangedCallback(bool newValue) {
OnDialogOpened(dialogOpenedEventArgs);
DialogOpenedCallback?.Invoke(this, dialogOpenedEventArgs);
CurrentSession?.ShowOpened(this, dialogOpenedEventArgs);
-
- // dialogHost._overlayPopupHost?.ConfigurePosition(dialogHost._root, PlacementMode.AnchorAndGravity, new Point());
}
else {
- RemoveAllHost();
+ for (var i = _overlayPopupHosts.Count - 1; i >= 0; i--)
+ {
+ var session = _overlayPopupHosts[i].Session;
+ InternalClose(session, session.CloseParameter, false);
+ }
_restoreFocusDialogClose?.Focus();
}
@@ -799,25 +801,9 @@ public void RemoveDispose(DialogOverlayPopupHost host) {
return host.DialogTaskCompletionSource;
}
- private void RemoveHost(DialogOverlayPopupHost? host) {
- if (host == null) {
- return;
- }
-
- var session = host.Session;
- if (!session.IsEnded) {
- session.Close(session.CloseParameter);
- return;
- }
-
- //DialogSession.Close may attempt to cancel the closing of the dialog.
- //When the dialog is closed in this manner it is not valid
- if (!session.IsEnded) {
- throw new InvalidOperationException($"Cannot cancel dialog closing after {nameof(IsOpen)} property has been set to {bool.FalseString}");
- }
-
+ private void RemoveHost(DialogOverlayPopupHost host) {
//NB: _dialogTaskCompletionSource is only set in the case where the dialog is shown with Show
- host.DialogTaskCompletionSource.TrySetResult(session.CloseParameter);
+ host.DialogTaskCompletionSource.TrySetResult(host.Session.CloseParameter);
host.IsOpen = false;
host.Content = null;
@@ -830,12 +816,6 @@ private void RemoveHost(DialogOverlayPopupHost? host) {
}
}
- private void RemoveAllHost() {
- foreach (var host in _overlayPopupHosts.ToArray().Reverse()) {
- RemoveHost(host);
- }
- }
-
private void ContentCoverGrid_OnPointerReleased(object sender, PointerReleasedEventArgs e) {
if (CloseOnClickAway && CurrentSession != null) {
InternalClose(CloseOnClickAwayParameter);
@@ -873,10 +853,10 @@ public event EventHandler DialogClosing {
internal void InternalClose(object? parameter) {
var session = CurrentSession ?? throw new InvalidOperationException($"{nameof(DialogHost)} does not have a current session");
- InternalClose(session, parameter);
+ InternalClose(session, parameter, true);
}
- internal void InternalClose(DialogSession session, object? parameter) {
+ internal void InternalClose(DialogSession session, object? parameter, bool canBeCancelled) {
session.CloseParameter = parameter;
session.IsEnded = true;
@@ -884,7 +864,7 @@ internal void InternalClose(DialogSession session, object? parameter) {
// * routed event
// * straight forward IsOpen dependency property
// * handler provided to the async show method
- var dialogClosingEventArgs = new DialogClosingEventArgs(session, DialogClosingEvent);
+ var dialogClosingEventArgs = new DialogClosingEventArgs(session, DialogClosingEvent, canBeCancelled);
OnDialogClosing(dialogClosingEventArgs);
DialogClosingCallback?.Invoke(this, dialogClosingEventArgs);
session.ShowClosing(this, dialogClosingEventArgs);
diff --git a/DialogHost.Avalonia/DialogSession.cs b/DialogHost.Avalonia/DialogSession.cs
index bcfa5d7..6b6d822 100644
--- a/DialogHost.Avalonia/DialogSession.cs
+++ b/DialogHost.Avalonia/DialogSession.cs
@@ -58,7 +58,7 @@ public void Close()
{
if (IsEnded) throw new InvalidOperationException("Dialog session has ended.");
- _owner.InternalClose(this, null);
+ _owner.InternalClose(this, null, true);
}
///
@@ -70,7 +70,7 @@ public void Close(object? parameter)
{
if (IsEnded) throw new InvalidOperationException("Dialog session has ended.");
- _owner.InternalClose(this, parameter);
+ _owner.InternalClose(this, parameter, true);
}
internal void ShowOpened(object obj, DialogOpenedEventArgs args) {