using System; using System.ComponentModel; using System.Linq; using System.Windows; namespace WxOrder.Framework.Commons.Dialogs { /// /// 静态弹窗服务:不依赖容器,直接传入 View 实例弹出。 /// ViewModel 需实现 IDialogAware。 /// public static class DialogService { // ========== 对外接口 ========== public static bool ExistsWindow(FrameworkElement view) { var window = Application.Current.Windows.OfType().FirstOrDefault(w => w.Content != null && w.Content.GetType() == view.GetType()); return window != null; } public static void ActivateWindow(FrameworkElement view) { var window = Application.Current.Windows.OfType().FirstOrDefault(w => w.Content != null && w.Content.GetType() == view.GetType()); if (window == null) return; if (!window.IsVisible) window.Show(); if (window.WindowState == WindowState.Minimized) window.WindowState = WindowState.Normal; if (!window.Activate()) { // 窗口被其他进程遮挡时,短暂置顶以切换到用户面前。 window.Topmost = true; window.Topmost = false; window.Activate(); } } public static void ShowOrActivateWindow(FrameworkElement view, IDialogParameters parameters = null, Action callback = null) { if (ExistsWindow(view)) { ActivateWindow(view); } else { Show(view, parameters, callback); } } /// 非模态弹出 public static void Show(FrameworkElement view, IDialogParameters parameters = null, Action callback = null, IDialogWindow window = null) { ShowInternal(view, parameters, callback, false, window); } /// 模态弹出 public static void ShowDialog(FrameworkElement view, IDialogParameters parameters = null, Action callback = null, IDialogWindow window = null) { ShowInternal(view, parameters, callback, true, window); } // ========== 内部实现 ========== private static void ShowInternal(FrameworkElement view, IDialogParameters parameters, Action callback, bool isModal, IDialogWindow window) { if (view == null) throw new ArgumentNullException(nameof(view)); if (parameters == null) parameters = new DialogParameters(); // 1. 创建(或使用传入的)DialogWindow var dialogWindow = window ?? new DialogWindow(); // 2. 绑定事件(关闭、回调等) ConfigureDialogWindowEvents(dialogWindow, callback); // 3. 配置内容(View + ViewModel) ConfigureDialogWindowContent(view, dialogWindow, parameters); // 4. 弹出 ShowDialogWindow(dialogWindow, isModal); } private static void ShowDialogWindow(IDialogWindow dialogWindow, bool isModal) { if (isModal) dialogWindow.ShowDialog(); else dialogWindow.Show(); } /// /// 把 View 挂到 DialogWindow 上,并触发 OnDialogOpened。 /// private static void ConfigureDialogWindowContent(FrameworkElement dialogContent, IDialogWindow window, IDialogParameters parameters) { // 不再自动绑 ViewModel,DataContext 由 View 自己负责 if (!(dialogContent.DataContext is IDialogAware viewModel)) throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface"); ConfigureDialogWindowProperties(window, dialogContent, viewModel); // 直接触发 OnDialogOpened(替代 MvvmHelpers.ViewAndViewModelAction) viewModel.OnDialogOpened(parameters); } /// /// 绑定 DialogWindow 的生命周期事件。 /// private static void ConfigureDialogWindowEvents(IDialogWindow dialogWindow, Action callback) { Action requestCloseHandler = null; requestCloseHandler = (o) => { dialogWindow.Result = o; dialogWindow.Close(); }; RoutedEventHandler loadedHandler = null; loadedHandler = (o, e) => { dialogWindow.Loaded -= loadedHandler; GetDialogViewModel(dialogWindow).RequestClose += requestCloseHandler; }; dialogWindow.Loaded += loadedHandler; CancelEventHandler closingHandler = null; closingHandler = (o, e) => { if (!GetDialogViewModel(dialogWindow).CanCloseDialog()) e.Cancel = true; }; dialogWindow.Closing += closingHandler; EventHandler closedHandler = null; closedHandler = (o, e) => { dialogWindow.Closed -= closedHandler; dialogWindow.Closing -= closingHandler; GetDialogViewModel(dialogWindow).RequestClose -= requestCloseHandler; GetDialogViewModel(dialogWindow).OnDialogClosed(); if (dialogWindow.Result == null) dialogWindow.Result = new DialogResult(); callback?.Invoke(dialogWindow.Result); dialogWindow.DataContext = null; dialogWindow.Content = null; }; dialogWindow.Closed += closedHandler; } /// /// 设置 DialogWindow 的 Style / Content / DataContext / Owner。 /// private static void ConfigureDialogWindowProperties(IDialogWindow window, FrameworkElement dialogContent, IDialogAware viewModel) { var windowStyle = Dialog.GetWindowStyle(dialogContent); if (windowStyle != null) window.Style = windowStyle; window.Content = dialogContent; window.DataContext = viewModel; // 宿主窗口和对话框共享同一个 DataContext if (window.Owner == null) window.Owner = Application.Current?.Windows .OfType() .FirstOrDefault(x => x.IsActive); } /// /// 从 window.Content 或 window.DataContext 里拿 IDialogAware。 /// 替代 Prism 的 dialogWindow.GetDialogViewModel() 扩展方法。 /// private static IDialogAware GetDialogViewModel(IDialogWindow window) { if (window.Content is FrameworkElement fe) { if (fe is IDialogAware aware) return aware; if (fe.DataContext is IDialogAware vm) return vm; } if (window.DataContext is IDialogAware wvm) return wvm; throw new NullReferenceException("A dialog's ViewModel must implement the IDialogAware interface"); } } }