以下是我为解决我最初的问题而提出的解决方案。从本质上讲,DialogServiceEx 支持选择性地激活现有的无模式对话框,而不是显示第二个副本。此外,对话框所有者也是可选的;这允许对话框独立于所有者(可以独立最小化等)
注意:该服务不是线程安全的。假设对话框只会显示在 UI 线程上。
public class DialogServiceEx : DialogService, IDialogServiceEx
{
private readonly Dictionary<string, IDialogWindow> _reusableDialogWindows = new Dictionary<string, IDialogWindow>();
public DialogServiceEx(IContainerExtension containerExtension)
: base(containerExtension)
{
}
public void Show(
string name,
IDialogParameters parameters,
Action<IDialogResult> callback,
bool reuseExistingWindow,
bool setOwner = true)
=> ShowDialogInternalEx(name, parameters, callback, null, reuseExistingWindow, setOwner);
public void Show(
string name,
IDialogParameters parameters,
Action<IDialogResult> callback,
string windowName,
bool reuseExistingWindow,
bool setOwner = true)
=> ShowDialogInternalEx(name, parameters, callback, windowName, reuseExistingWindow, setOwner);
private void ShowDialogInternalEx(
string name,
IDialogParameters parameters,
Action<IDialogResult> callback,
string windowName,
bool reuseExistingWindow,
bool setOwner)
{
string dialogKey = $"{name}-{windowName}";
if (reuseExistingWindow &&
_reusableDialogWindows.TryGetValue($"{name}-{windowName}", out IDialogWindow dialogWindow))
{
dialogWindow.Show();
if (dialogWindow is Window window)
{
// NOTE: IDialogWindow should always be a Window under WPF.
if (window.WindowState == WindowState.Minimized)
{
window.WindowState = WindowState.Normal;
}
window.Activate();
return;
}
}
dialogWindow = CreateDialogWindow(windowName);
if (reuseExistingWindow)
{
_reusableDialogWindows.Add(dialogKey, dialogWindow);
dialogWindow.Closed +=
(_, __) =>
{
Debug.Assert(_reusableDialogWindows.ContainsKey(dialogKey), "Expect single-threaded access only.");
_reusableDialogWindows.Remove(dialogKey);
};
}
ConfigureDialogWindowEvents(dialogWindow, callback);
ConfigureDialogWindowContent(name, dialogWindow, parameters ?? new DialogParameters());
if (setOwner == false)
{
dialogWindow.Owner = null;
}
ShowDialogWindow(dialogWindow, false);
}
}