using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; using System.Windows.Media.Animation; using XFEToolBox.Client.Views.Windows; using XFEToolBox.Client.Model; using XFEToolBox.Client.Views.Pages.Popups; namespace XFEToolBox.Client.Utilities; public static class PopupHelper { private const double DimmedOwnerOpacity = 0.58; private static NormalDialogPopupPage CreateNormalDialogPage(object content) { var dialogPage = new NormalDialogPopupPage(); dialogPage.ViewModel.Content = content; return dialogPage; } private static ScrollViewer CreateTextContent(string text, Color textColor) { var content = new ScrollViewer { Content = new TextBlock { Text = text, Foreground = new SolidColorBrush(textColor), Margin = new Thickness(20, 20, 20, 0), TextWrapping = TextWrapping.WrapWithOverflow }, HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled, VerticalScrollBarVisibility = ScrollBarVisibility.Auto }; // 精简工具宿主只加载 ToolThemeResources,不一定包含主程序遗留的 ConsoleScrollBar 键。 // 优先复用可用的工具箱样式;两者都不存在时保留隐式/系统 ScrollBar 样式,不能让弹窗崩溃。 var scrollBarStyle = Application.Current?.TryFindResource("ConsoleScrollBar") as Style ?? Application.Current?.TryFindResource("ToolBoxScrollBarStyle") as Style; if (scrollBarStyle is not null) { content.Resources[typeof(ScrollBar)] = new Style(typeof(ScrollBar), scrollBarStyle); } return content; } public static MessageBoxResult? ShowConfirmDialog(object content, bool showCancelButton = false, string confirmText = "确定", string cancelText = "取消") => ShowConfirmDialog(content, new PopupWindowOptions(), showCancelButton, confirmText, cancelText); public static MessageBoxResult? ShowConfirmDialog(object content, PopupWindowOptions options, bool showCancelButton = false, string confirmText = "确定", string cancelText = "取消") { var dialog = CreateNormalDialogPage(content); dialog.ViewModel.ConfirmText = confirmText; dialog.ViewModel.CancelText = cancelText; dialog.ViewModel.ConfirmGridLength = new GridLength(1, GridUnitType.Star); if (showCancelButton) dialog.ViewModel.CancelGridLength = new GridLength(1, GridUnitType.Star); return ShowDialog(dialog, options); } public static MessageBoxResult? ShowConfirmDialog(string text, Color textColor, bool showCancelButton = false, string confirmText = "确定", string cancelText = "取消") => ShowConfirmDialog(CreateTextContent(text, textColor), showCancelButton, confirmText, cancelText); public static MessageBoxResult? ShowConfirmDialog(string text, bool showCancelButton = false, string confirmText = "确定", string cancelText = "取消") => ShowConfirmDialog(text, Colors.Black, showCancelButton, confirmText, cancelText); public static MessageBoxResult? ShowConfirmDialog(string text, PopupWindowOptions options, bool showCancelButton = false, string confirmText = "确定", string cancelText = "取消") => ShowConfirmDialog(CreateTextContent(text, Colors.Black), options, showCancelButton, confirmText, cancelText); public static MessageBoxResult? ShowYesOrNoDialog(object content, bool showCancelButton = false, string yesText = "是", string noText = "否") => ShowYesOrNoDialog(content, new PopupWindowOptions(), showCancelButton, yesText, noText); public static MessageBoxResult? ShowYesOrNoDialog(object content, PopupWindowOptions options, bool showCancelButton = false, string yesText = "是", string noText = "否") { var dialog = CreateNormalDialogPage(content); dialog.ViewModel.YesText = yesText; dialog.ViewModel.NoText = noText; dialog.ViewModel.YesGridLength = new GridLength(1, GridUnitType.Star); dialog.ViewModel.NoGridLength = new GridLength(1, GridUnitType.Star); if (showCancelButton) dialog.ViewModel.CancelGridLength = new GridLength(1, GridUnitType.Star); return ShowDialog(dialog, options); } public static MessageBoxResult? ShowYesOrNoDialog(string text, Color textColor, bool showCancelButton = false, string yesText = "是", string noText = "否") => ShowYesOrNoDialog(CreateTextContent(text, textColor), showCancelButton, yesText, noText); public static MessageBoxResult? ShowYesOrNoDialog(string text, bool showCancelButton = false, string yesText = "是", string noText = "否") => ShowYesOrNoDialog(text, Colors.Black, showCancelButton, yesText, noText); public static MessageBoxResult? ShowYesOrNoDialog(string text, PopupWindowOptions options, bool showCancelButton = false, string yesText = "是", string noText = "否") => ShowYesOrNoDialog(CreateTextContent(text, Colors.Black), options, showCancelButton, yesText, noText); public static MessageBoxResult? ShowDialog(object content, double width = 320, double height = 230) => ShowDialog(content, new PopupWindowOptions { Width = width, Height = height }); /// /// 使用主窗体风格的通用弹窗显示任意页面或控件。 /// /// 要显示的 Page、UserControl 或其他内容。 /// 标题、副标题、尺寸、Owner 与交互选项。 public static MessageBoxResult? ShowDialog(object content, PopupWindowOptions options) { ArgumentNullException.ThrowIfNull(content); ArgumentNullException.ThrowIfNull(options); options.Owner ??= Application.Current?.Windows.OfType() .FirstOrDefault(window => window.IsActive && window is not PopupWindow); var popupWindow = new PopupWindow(); popupWindow.ApplyOptions(options); popupWindow.ViewModel.Content = content; if (content is IPopupPage popupPage) popupPage.PopupWindow = popupWindow; var owner = options.Owner; var originalOwnerOpacity = owner?.Opacity ?? 1; try { if (options.DimOwner && owner is not null) AnimateOwnerOpacity(owner, Math.Min(originalOwnerOpacity, DimmedOwnerOpacity), 140); popupWindow.ShowDialog(); } finally { if (options.DimOwner && owner is not null) RestoreOwnerOpacity(owner, originalOwnerOpacity); } return popupWindow.Result; } private static void AnimateOwnerOpacity(Window owner, double targetOpacity, int durationMilliseconds) { owner.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation( owner.Opacity, targetOpacity, TimeSpan.FromMilliseconds(durationMilliseconds)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }, FillBehavior = FillBehavior.HoldEnd }); } private static void RestoreOwnerOpacity(Window owner, double originalOpacity) { var currentOpacity = owner.Opacity; owner.BeginAnimation(UIElement.OpacityProperty, null); owner.Opacity = originalOpacity; owner.BeginAnimation(UIElement.OpacityProperty, new DoubleAnimation( currentOpacity, originalOpacity, TimeSpan.FromMilliseconds(170)) { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut }, FillBehavior = FillBehavior.Stop }); } }