WPF:消息框.在窗口中显示.在还原窗口关闭崩溃



我有一个简单的WPF应用程序,有一个主窗口和一个子窗口。子窗口应在关闭时要求确认。

public partial class MainWindow : Window
{
Window childWindow;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
childWindow = new Window();
childWindow.Owner = this;
childWindow.Closing += ChildWindow_Closing;
childWindow.Show();
}
private void ChildWindow_Closing(object sender, CancelEventArgs e)
{
MessageBox.Show(childWindow, "Close child window?");
}
}

如果单击任务栏上的"显示桌面",然后单击"显示打开的窗口",则显示确认对话框时,应用程序将崩溃并出现异常:

System.InvalidOperationException occurred
HResult=0x80131509
Message=Cannot set Visibility to Visible or call Show, ShowDialog, Close, or WindowInteropHelper.EnsureHandle while a Window is closing.
Source=PresentationFramework
StackTrace:
at System.Windows.Window.VerifyNotClosing()
at System.Windows.Window.CoerceVisibility(DependencyObject d, Object value)
at System.Windows.DependencyObject.ProcessCoerceValue(DependencyProperty dp, PropertyMetadata metadata, EntryIndex& entryIndex, Int32& targetIndex, EffectiveValueEntry& newEntry, EffectiveValueEntry& oldEntry, Object& oldValue, Object baseValue, Object controlValue, CoerceValueCallback coerceValueCallback, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, Boolean skipBaseValueChecks)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
at System.Windows.Window.UpdateVisibilityProperty(Visibility value)
at System.Windows.Window.WmShowWindow(IntPtr wParam, IntPtr lParam)
at System.Windows.Window.WindowFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at System.Windows.Interop.HwndSource.PublicHooksFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)

如果将 MessageBox 对话框的所有者替换为主窗口(替换为"this"(,则不会发生异常。

这里可能有什么问题?

你能发布你的 XAML 代码吗?请参阅下面我在 MainWindow.xaml 中的内容,将您的代码复制到 MainWindow 中.cs并且该应用程序符合并运行正常。

<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>

抱歉,这没有多大帮助,无法重现您的异常。

编辑:另一个想法,您可以尝试使用

childWindow.ShowDialog();

进一步编辑:

根据您的评论,我找到了导致异常的原因。在使用"显示桌面"功能之前,任务栏中会打开两个应用程序窗口。随后,当尝试从任务栏还原应用时,子窗口不再可见。Windows似乎做出了判断,提前丢失了关闭的子窗口。因此,当您单击主窗口缩略图时,应用程序会尝试显示父窗口,但无法设置其可见性,而其子窗口正在关闭过程中。

可能很少有方法可以做到这一点,但在关闭时隐藏子窗口可能是其中之一。或者,您可以暂时隐藏主窗口,这也可以防止异常。前一种解决方案将可见性返回到父窗口,假设子窗口将关闭(如果未将其设置为再次可见(,后者将子窗口保留为唯一可见的窗口,并强制 Windows 在任务栏中显示其缩略图。

private void ChildWindow_Closing(object sender, CancelEventArgs e)
{
childWindow.Visibility = Visibility.Hidden;
MessageBox.Show(childWindow, "Close child window?");
}

private void ChildWindow_Closing(object sender, CancelEventArgs e)
{
Visibility = Visibility.Hidden;
MessageBox.Show(childWindow, "Close child window?");
Visibility = Visibility.Visible;
}

最新更新