diff --git a/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml b/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml index d9d725425..a0af3d9d8 100644 --- a/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml +++ b/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml @@ -100,14 +100,15 @@ Native Window: - + + - + Some descriptions @@ -119,7 +120,7 @@ IsOpen="{Binding IsInformationMsgBoxOpened, Mode=TwoWay}" Style="Information" HostType="{Binding MessageBoxStyleCaseHostType}"> - + some messages...some messages... some messages...some messages... @@ -132,7 +133,7 @@ Style="Success" HostType="{Binding MessageBoxStyleCaseHostType}" IsOpen="{Binding IsSuccessMsgBoxOpened, Mode=TwoWay}"> - + some messages...some messages... some messages...some messages... @@ -145,7 +146,7 @@ Style="Error" HostType="{Binding MessageBoxStyleCaseHostType}" IsOpen="{Binding IsErrorMsgBoxOpened, Mode=TwoWay}"> - + some messages...some messages... some messages...some messages... @@ -158,14 +159,23 @@ Style="Warning" HostType="{Binding MessageBoxStyleCaseHostType}" IsOpen="{Binding IsWarningMsgBoxOpened, Mode=TwoWay}"> - + some messages...some messages... some messages...some messages... Warning - + + + + + Confirm + Information + Success + Error + Warning + diff --git a/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml.cs b/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml.cs index 577e3576a..32dfb1caf 100644 --- a/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml.cs +++ b/controlgallery/AtomUIGallery/ShowCases/Views/Feedback/ModalShowCase.axaml.cs @@ -259,7 +259,7 @@ public partial class ModalShowCase : ReactiveUserControl // 鼠标会被卡死,强制刷新一次事件循环 await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); var content = BuildDialogContent(); - var options = new DialogOptions() + var options = new DialogOptions { IsModal = true, Title = "Basic Modal", @@ -272,7 +272,7 @@ public partial class ModalShowCase : ReactiveUserControl VerticalOffset = new Dimension(30, DimensionUnitType.Percentage), MinWidth = 400 }; - Dialog.ShowDialog(content, null, options); + await Dialog.ShowDialogAsync(content, null, options); } private async void HandleOpenWindowDialogButtonClick(object? sender, RoutedEventArgs e) @@ -280,7 +280,7 @@ public partial class ModalShowCase : ReactiveUserControl // 鼠标会被卡死,强制刷新一次事件循环 await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); var content = BuildDialogContent(); - var options = new DialogOptions() + var options = new DialogOptions { IsModal = true, Title = "Basic Modal", @@ -294,14 +294,14 @@ public partial class ModalShowCase : ReactiveUserControl VerticalOffset = new Dimension(30, DimensionUnitType.Percentage), MinWidth = 400 }; - Dialog.ShowDialog(content, null, options); + await Dialog.ShowDialogAsync(content, null, options); } private async void HandleOpenCustomViewDialogButtonClick(object? sender, RoutedEventArgs e) { // 鼠标会被卡死,强制刷新一次事件循环 await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); - var options = new DialogOptions() + var options = new DialogOptions { IsModal = true, Title = "Basic Modal", @@ -318,30 +318,124 @@ public partial class ModalShowCase : ReactiveUserControl var viewModel = new ModalUserControlViewModel() { Name = "AtomUI", - Age = 2 + Age = 2 }; Dialog.ShowDialog(viewModel, options); } private Control BuildDialogContent() { - var stackPanel = new StackPanel() + var stackPanel = new StackPanel { Orientation = Orientation.Vertical, Spacing = 5 }; - stackPanel.Children.Add(new TextBlock() + stackPanel.Children.Add(new TextBlock { Text = "Some contents..." }); - stackPanel.Children.Add(new TextBlock() + stackPanel.Children.Add(new TextBlock { Text = "Some contents..." }); - stackPanel.Children.Add(new TextBlock() + stackPanel.Children.Add(new TextBlock { Text = "Some contents..." }); return stackPanel; } + + private async void HandleCreateConfirmMessageBox(object? sender, RoutedEventArgs e) + { + await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); + var content = BuildMessageBoxContent(); + var options = new MessageBoxOptions() + { + IsModal = true, + Title = "Do you want to delete these items?", + IsDragMovable = true, + IsCenterOnStartup = true, + Style = MessageBoxStyle.Confirm + }; + await MessageBox.ShowMessageAsync(content, null, options); + } + + private async void HandleCreateInformationMessageBox(object? sender, RoutedEventArgs e) + { + await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); + var content = BuildMessageBoxContent(); + var options = new MessageBoxOptions() + { + IsModal = true, + Title = "This is a notification message", + IsDragMovable = true, + IsCenterOnStartup = true, + Style = MessageBoxStyle.Information + }; + await MessageBox.ShowMessageAsync(content, null, options); + } + + private async void HandleCreateSuccessMessageBox(object? sender, RoutedEventArgs e) + { + await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); + var content = BuildMessageBoxContent(); + var options = new MessageBoxOptions() + { + IsModal = true, + Title = "Operation successful", + IsDragMovable = true, + IsCenterOnStartup = true, + Style = MessageBoxStyle.Success + }; + await MessageBox.ShowMessageAsync(content, null, options); + } + + private async void HandleCreateErrorMessageBox(object? sender, RoutedEventArgs e) + { + await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); + var content = BuildMessageBoxContent(); + var options = new MessageBoxOptions() + { + IsModal = true, + Title = "This is an error message", + IsDragMovable = true, + IsCenterOnStartup = true, + Style = MessageBoxStyle.Error + }; + await MessageBox.ShowMessageAsync(content, null, options); + } + + private async void HandleCreateWarningMessageBox(object? sender, RoutedEventArgs e) + { + await Dispatcher.UIThread.InvokeAsync(() => { }, DispatcherPriority.Background); + var content = BuildMessageBoxContent(); + var options = new MessageBoxOptions() + { + IsModal = true, + Title = "This is a warning message", + IsDragMovable = true, + IsCenterOnStartup = true, + Style = MessageBoxStyle.Warning + }; + await MessageBox.ShowMessageAsync(content, null, options); + } + + private Control BuildMessageBoxContent() + { + var stackPanel = new StackPanel + { + Orientation = Orientation.Vertical, + Spacing = 5 + }; + stackPanel.Children.Add(new TextBlock + { + Text = "some messages...some messages..." + }); + stackPanel.Children.Add(new TextBlock + { + Text = "some messages...some messages..." + }); + return stackPanel; + } + } \ No newline at end of file diff --git a/src/AtomUI.Desktop.Controls/Dialog/Dialog.StaticAPI.cs b/src/AtomUI.Desktop.Controls/Dialog/Dialog.StaticAPI.cs index 108d81436..e278b197b 100644 --- a/src/AtomUI.Desktop.Controls/Dialog/Dialog.StaticAPI.cs +++ b/src/AtomUI.Desktop.Controls/Dialog/Dialog.StaticAPI.cs @@ -1,6 +1,5 @@ -using Avalonia; using Avalonia.Controls; -using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Threading; using Avalonia.VisualTree; namespace AtomUI.Desktop.Controls; @@ -36,7 +35,7 @@ public partial class Dialog return result; } - public static Task? ShowDialogAsync(TViewModel? dataContext, DialogOptions? options = null, TopLevel? topLevel = null) + public static async Task ShowDialogAsync(TViewModel? dataContext, DialogOptions? options = null, TopLevel? topLevel = null) where TView : Control, new() { var dialogManager = FindDialogManager(topLevel); @@ -47,10 +46,10 @@ public partial class Dialog } dialog.Closed += (_, _) => dialogManager.Children.Remove(dialog); dialogManager.Children.Add(dialog); - return dialog.OpenAsync(); + await Dispatcher.UIThread.InvokeAsync(async () => await dialog.OpenAsync()); } - public static Task? ShowDialogAsync(Control content, object? dataContext = null, DialogOptions? options = null, TopLevel? topLevel = null) + public static async Task ShowDialogAsync(Control content, object? dataContext = null, DialogOptions? options = null, TopLevel? topLevel = null) { var dialogManager = FindDialogManager(topLevel); var dialog = CreateDialog(content, dataContext, options); @@ -60,7 +59,7 @@ public partial class Dialog } dialog.Closed += (_, _) => dialogManager.Children.Remove(dialog); dialogManager.Children.Add(dialog); - return dialog.OpenAsync(); + await Dispatcher.UIThread.InvokeAsync(async () => await dialog.OpenAsync()); } private static Dialog CreateDialog(Control content, object? dataContext, DialogOptions? options) @@ -99,7 +98,7 @@ public partial class Dialog private static GlobalDialogManager FindDialogManager(TopLevel? topLevel) { - var toplevel = topLevel ?? GetMainWindow(); + var toplevel = topLevel ?? Window.GetMainWindow(); var dialogManager = toplevel.FindDescendantOfType(); if (dialogManager == null) { @@ -107,14 +106,4 @@ public partial class Dialog } return dialogManager; } - - private static Window? GetMainWindow() - { - var lifetime = Application.Current?.ApplicationLifetime; - if (lifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime) - { - return desktopLifetime.MainWindow as Window; - } - return null; - } } \ No newline at end of file diff --git a/src/AtomUI.Desktop.Controls/Dialog/Dialog.cs b/src/AtomUI.Desktop.Controls/Dialog/Dialog.cs index f887ca298..6d751c0dd 100644 --- a/src/AtomUI.Desktop.Controls/Dialog/Dialog.cs +++ b/src/AtomUI.Desktop.Controls/Dialog/Dialog.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reactive.Disposables; using System.Reactive.Disposables.Fluent; -using System.Reactive.Linq; using AtomUI.Controls; using AtomUI.Data; using AtomUI.Desktop.Controls.DialogPositioning; @@ -275,12 +274,6 @@ public partial class Dialog : TemplatedControl, set => SetValue(DialogHostTypeProperty, value); } - public Task? ResultTask - { - get; - private set; - } - public DialogStandardButtons StandardButtons { get => GetValue(StandardButtonsProperty); @@ -401,7 +394,6 @@ public partial class Dialog : TemplatedControl, private bool _ignoreIsOpenChanged; private DialogOpenState? _openState; private Action? _dialogHostChangedHandler; - private IDisposable? _modalSubscription; private CancellationTokenSource? _frameCancellationTokenSource; private bool _startupLocationCalculated; private bool _opening; @@ -446,16 +438,16 @@ public partial class Dialog : TemplatedControl, var token = _frameCancellationTokenSource.Token; var frame = new DispatcherFrame(); token.Register(() => frame.Continue = false); - var resultTask = OpenAsync(); + var _ = OpenAsync(); Dispatcher.UIThread.PushFrame(frame); - return resultTask?.Result; + return Result; } - public Task? OpenAsync() + public async Task OpenAsync() { if (_openState != null || _opening) { - return null; + return; } _opening = true; @@ -466,7 +458,7 @@ public partial class Dialog : TemplatedControl, IDialogHost? dialogHost = null; CompositeDisposable relayBindingDisposables = new CompositeDisposable(); DialogHost? windowDialogHost = null; - OverlayDialogHost? overlayDialogHost = null; + if (DialogHostType == DialogHostType.Window) { windowDialogHost = CreateDialogHost(topLevel, this); @@ -479,7 +471,7 @@ public partial class Dialog : TemplatedControl, var dialogLayer = DialogLayer.GetDialogLayer(placementTarget); if (dialogLayer != null) { - overlayDialogHost = CreateOverlayDialogHost(dialogLayer, this); + var overlayDialogHost = CreateOverlayDialogHost(dialogLayer, this); OverlayInputPassThroughElement = overlayDialogHost; RelayOverlayDialogBindings(relayBindingDisposables, overlayDialogHost); overlayDialogHost.CustomButtons.AddRange(CustomButtons); @@ -535,6 +527,12 @@ public partial class Dialog : TemplatedControl, } var inputManager = AvaloniaLocator.Current.GetService(); inputManager?.Process.Subscribe(ListenForNonClientClick).DisposeWith(handlerCleanup); + + TaskCompletionSource? modalTsc = null; + if (IsModal) + { + modalTsc = new TaskCompletionSource(); + } var cleanupPopup = Disposable.Create((dialogHost, handlerCleanup), state => { @@ -554,6 +552,7 @@ public partial class Dialog : TemplatedControl, dialogAwareDataContext.NotifyClosed(); } Closed?.Invoke(this, EventArgs.Empty); + modalTsc?.TrySetResult(); }); if (DialogHostType == DialogHostType.Window) { @@ -596,7 +595,7 @@ public partial class Dialog : TemplatedControl, { if (topLevel is Window windowTopLevel) { - windowDialog.ShowDialog(windowTopLevel); + await windowDialog.ShowDialog(windowTopLevel); } } else @@ -609,32 +608,6 @@ public partial class Dialog : TemplatedControl, dialogHost.Show(); } - if (IsModal) - { - var tcs = new TaskCompletionSource(); - - var disposables = new CompositeDisposable( - [ - Observable.FromEventPattern( - x => Closed += x, - x => Closed -= x) - .Take(1) - .Subscribe(_ => - { - _modalSubscription?.Dispose(); - }), - Disposable.Create(() => - { - _modalSubscription = null; - // owner!.Activate(); - tcs.SetResult(Result); - }) - ]); - - _modalSubscription = disposables; - ResultTask = tcs.Task; - } - using (BeginIgnoringIsOpen()) { SetCurrentValue(IsOpenProperty, true); @@ -642,8 +615,10 @@ public partial class Dialog : TemplatedControl, Opened?.Invoke(this, EventArgs.Empty); _opening = false; _dialogHostChangedHandler?.Invoke(Host); - - return ResultTask; + if (modalTsc != null) + { + await modalTsc.Task; + } } private protected virtual DialogHost CreateDialogHost(TopLevel topLevel, Dialog dialog) @@ -761,8 +736,6 @@ public partial class Dialog : TemplatedControl, _openState = null; _dialogHostChangedHandler?.Invoke(null); - _modalSubscription?.Dispose(); - _modalSubscription = null; using (BeginIgnoringIsOpen()) { SetCurrentValue(IsOpenProperty, false); diff --git a/src/AtomUI.Desktop.Controls/Dialog/DialogOptions.cs b/src/AtomUI.Desktop.Controls/Dialog/DialogOptions.cs index 2d56fca79..c9e5c19fe 100644 --- a/src/AtomUI.Desktop.Controls/Dialog/DialogOptions.cs +++ b/src/AtomUI.Desktop.Controls/Dialog/DialogOptions.cs @@ -1,4 +1,3 @@ -using AtomUI.Controls; using Avalonia.Controls; namespace AtomUI.Desktop.Controls; @@ -7,11 +6,14 @@ public record DialogOptions { public string? Title { get; init; } public PathIcon? TitleIcon { get; init; } - public bool IsLightDismissEnabled { get; init; } = false; + /// + /// 次选项仅 Overlay Host 类型的弹窗有效 + /// + public bool IsLightDismissEnabled { get; init; } public bool IsModal { get; init; } = true; - public bool IsResizable { get; init; } = false; + public bool IsResizable { get; init; } public bool IsClosable { get; init; } = true; - public bool IsMaximizable { get; init; } = false; + public bool IsMaximizable { get; init; } public double MaxHeight { get; init; } = double.PositiveInfinity; public double MaxWidth { get; init; } = double.PositiveInfinity; @@ -21,11 +23,11 @@ public record DialogOptions public double Height { get; init; } = double.NaN; /// - /// 仅仅对 Window Host 类型的弹窗有效 + /// 次选项仅 Window Host 类型的弹窗有效 /// public bool IsMinimizable { get; init; } = true; - - public bool IsDragMovable { get; init; } = false; + + public bool IsDragMovable { get; init; } public bool IsFooterVisible { get; init; } = true; public Control? PlacementTarget { get; init; } public Dimension? HorizontalOffset { get; init; } diff --git a/src/AtomUI.Desktop.Controls/MessageBox/MessageBox.cs b/src/AtomUI.Desktop.Controls/MessageBox/MessageBox.cs index caa1788e2..f90153b24 100644 --- a/src/AtomUI.Desktop.Controls/MessageBox/MessageBox.cs +++ b/src/AtomUI.Desktop.Controls/MessageBox/MessageBox.cs @@ -11,6 +11,7 @@ using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; using Avalonia.Metadata; +using Avalonia.Threading; using Avalonia.VisualTree; namespace AtomUI.Desktop.Controls; @@ -38,7 +39,7 @@ public class MessageBox : TemplatedControl, public static readonly StyledProperty ContentTemplateProperty = Dialog.ContentTemplateProperty.AddOwner(); public static readonly StyledProperty StyleProperty = - AvaloniaProperty.Register(nameof (Style)); + AvaloniaProperty.Register(nameof (Style), MessageBoxStyle.Information); public static readonly StyledProperty IsMotionEnabledProperty = MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner(); @@ -250,37 +251,145 @@ public class MessageBox : TemplatedControl, public MessageBox() { - CustomButtons.CollectionChanged += new NotifyCollectionChangedEventHandler(HandleCustomButtonsChanged); + CustomButtons.CollectionChanged += HandleCustomButtonsChanged; } public object? Open() { - if (_dialog == null) - { - return null; - } + Debug.Assert(_dialog != null); return _dialog.Open(); } - public Task? OpenAsync() + public async Task OpenAsync() { - if (_dialog == null) - { - return null; - } - return _dialog.OpenAsync(); + Debug.Assert(_dialog != null); + await _dialog.OpenAsync(); } public void Cancel() { - _dialog?.Reject(); + Debug.Assert(_dialog != null); + _dialog.Reject(); } public void Confirm() { - _dialog?.Accept(); + Debug.Assert(_dialog != null); + _dialog.Accept(); } + #region 静态 API + + public static object? ShowMessageBox(TViewModel? dataContext, MessageBoxOptions? options = null, + TopLevel? topLevel = null) + where TView : Control, new() + { + var dialogManager = FindDialogManager(topLevel); + var messageBox = CreateMessageBox(new TView(), dataContext, options); + if (options?.HostType == DialogHostType.Window) + { + messageBox.PlacementTarget = dialogManager; + } + dialogManager.Children.Add(messageBox); + var result = messageBox.Open(); + dialogManager.Children.Remove(messageBox); + return result; + } + + public static object? ShowMessageBox(Control content, object? dataContext = null, MessageBoxOptions? options = null, TopLevel? topLevel = null) + { + var dialogManager = FindDialogManager(topLevel); + var messageBox = CreateMessageBox(content, dataContext, options); + if (options?.HostType == DialogHostType.Window) + { + messageBox.PlacementTarget = dialogManager; + } + dialogManager.Children.Add(messageBox); + var result = messageBox.Open(); + dialogManager.Children.Remove(messageBox); + return result; + } + + public static async Task ShowMessageBoxAsync(TViewModel? dataContext, MessageBoxOptions? options = null, TopLevel? topLevel = null) + where TView : Control, new() + { + var dialogManager = FindDialogManager(topLevel); + var messageBox = CreateMessageBox(new TView(), dataContext, options); + if (options?.HostType == DialogHostType.Window) + { + messageBox.PlacementTarget = dialogManager; + } + messageBox.Closed += (_, _) => dialogManager.Children.Remove(messageBox); + dialogManager.Children.Add(messageBox); + await Dispatcher.UIThread.InvokeAsync(async () => await messageBox.OpenAsync()); + return messageBox.Result; + } + + public static async Task ShowMessageAsync(Control content, object? dataContext = null, MessageBoxOptions? options = null, TopLevel? topLevel = null) + { + var dialogManager = FindDialogManager(topLevel); + var messageBox = CreateMessageBox(content, dataContext, options); + if (options?.HostType == DialogHostType.Window) + { + messageBox.PlacementTarget = dialogManager; + } + messageBox.Closed += (_, _) => dialogManager.Children.Remove(messageBox); + dialogManager.Children.Add(messageBox); + var tsc = new TaskCompletionSource(); + await Dispatcher.UIThread.InvokeAsync(async () => + { + await messageBox.OpenAsync(); + tsc.SetResult(messageBox.Result); + }); + await tsc.Task; + return messageBox.Result; + } + + private static MessageBox CreateMessageBox(Control content, object? dataContext, MessageBoxOptions? options) + { + var messageBox = new MessageBox() + { + Title = options?.Title, + IsLightDismissEnabled = options?.IsLightDismissEnabled ?? false, + IsModal = options?.IsModal ?? true, + IsDragMovable = options?.IsDragMovable ?? false, + Style = options?.Style ?? MessageBoxStyle.Information, + PlacementTarget = options?.PlacementTarget, + HorizontalOffset = options?.HorizontalOffset, + VerticalOffset = options?.VerticalOffset, + HostType = options?.HostType ?? DialogHostType.Overlay, + IsCenterOnStartup = options?.IsCenterOnStartup ?? true, + Content = content, + DataContext = dataContext, + Width = options?.Width ?? double.NaN, + Height = options?.Height ?? double.NaN, + MinWidth = options?.MinWidth ?? 0d, + MinHeight = options?.MinHeight ?? 0d, + MaxWidth = options?.MaxWidth ?? double.PositiveInfinity, + MaxHeight = options?.MaxHeight ?? double.PositiveInfinity, + IsConfirmLoading = options?.IsConfirmLoading ?? false, + IsLoading = options?.IsLoading ?? false, + }; + if (options?.Icon != null) + { + messageBox.Icon = options.Icon; + } + return messageBox; + } + + private static GlobalDialogManager FindDialogManager(TopLevel? topLevel) + { + var toplevel = topLevel ?? Window.GetMainWindow(); + var dialogManager = toplevel.FindDescendantOfType(); + if (dialogManager == null) + { + throw new InvalidOperationException("The DialogManager was not found in TopLevel; you may not be using the atom:Window class."); + } + return dialogManager; + } + + #endregion + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -306,13 +415,13 @@ public class MessageBox : TemplatedControl, base.OnApplyTemplate(e); if (_dialog != null) { - _dialog.Opened -= HandleDialogOpened; - _dialog.Closed -= HandleDialogClosed; - _dialog.Rejected -= HandleDialogCancelled; - _dialog.Accepted -= HandleDialogConfirmed; - _dialog.Finished -= HandleDialogFinished; + _dialog.Opened -= HandleDialogOpened; + _dialog.Closed -= HandleDialogClosed; + _dialog.Rejected -= HandleDialogCancelled; + _dialog.Accepted -= HandleDialogConfirmed; + _dialog.Finished -= HandleDialogFinished; } - _dialog = e.NameScope.Find(MessageBoxThemeConstants.DialogPart); + _dialog = e.NameScope.Find(MessageBoxThemeConstants.DialogPart); if (_dialog != null) { _dialog.Opened += HandleDialogOpened; @@ -450,4 +559,4 @@ public class MessageBox : TemplatedControl, } } } -} +} \ No newline at end of file diff --git a/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxDialog.cs b/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxDialog.cs index f8f80180b..5574f7bc4 100644 --- a/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxDialog.cs +++ b/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxDialog.cs @@ -1,5 +1,4 @@ using System.Reactive.Disposables; -using AtomUI.Controls; using AtomUI.Data; using AtomUI.Desktop.Controls.Primitives; using Avalonia; diff --git a/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxOptions.cs b/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxOptions.cs new file mode 100644 index 000000000..5919c67a1 --- /dev/null +++ b/src/AtomUI.Desktop.Controls/MessageBox/MessageBoxOptions.cs @@ -0,0 +1,31 @@ +using Avalonia.Controls; + +namespace AtomUI.Desktop.Controls; + +public record MessageBoxOptions +{ + public DialogHostType HostType { get; init; } = DialogHostType.Overlay; + public string? Title { get; init; } + public PathIcon? Icon { get; init; } + public MessageBoxStyle Style { get; init; } = MessageBoxStyle.Information; + public bool IsModal { get; init; } = true; + public bool IsDragMovable { get; init; } + public Control? PlacementTarget { get; init; } + public Dimension? HorizontalOffset { get; init; } + public Dimension? VerticalOffset { get; init; } + public bool IsCenterOnStartup { get; init; } = true; + /// + /// 次选项仅 Overlay Host 类型的弹窗有效 + /// + public bool IsLightDismissEnabled { get; init; } + + public bool IsLoading { get; init; } + public bool IsConfirmLoading { get; init; } + + public double MaxHeight { get; init; } = double.PositiveInfinity; + public double MaxWidth { get; init; } = double.PositiveInfinity; + public double MinHeight { get; init; } = 0d; + public double MinWidth { get; init; } = 0d; + public double Width { get; init; } = double.NaN; + public double Height { get; init; } = double.NaN; +} \ No newline at end of file diff --git a/src/AtomUI.Desktop.Controls/MessageBox/Themes/MessageBoxOverlayDialogHostTheme.axaml b/src/AtomUI.Desktop.Controls/MessageBox/Themes/MessageBoxOverlayDialogHostTheme.axaml index f8b61e7ae..23a0da226 100644 --- a/src/AtomUI.Desktop.Controls/MessageBox/Themes/MessageBoxOverlayDialogHostTheme.axaml +++ b/src/AtomUI.Desktop.Controls/MessageBox/Themes/MessageBoxOverlayDialogHostTheme.axaml @@ -61,19 +61,18 @@ - - + + + - -