WPF:MessageBox.Show在Window.OnClosing崩溃恢复窗口

时间:2017-07-21 19:10:59

标签: .net wpf windows-10

我有一个简单的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”),则不会发生异常。

这可能是错的?

1 个答案:

答案 0 :(得分:1)

你可以发布你的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();

进一步编辑:

根据您的评论,我找到了导致异常的原因。之前使用“显示桌面”&#39;功能,任务栏中打开了两个应用程序窗口。随后,当尝试从任务栏恢复应用程序时,子窗口不再可见。似乎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;
        }