【发布时间】:2012-01-18 10:03:13
【问题描述】:
在我的 WPF 应用程序中,我创建了一个窗口并通过 ShowDialog() 方法调用它以将其显示为对话框。但是当我通过 Close() 方法关闭窗口时,不会为此对话框窗口触发 Unloaded 事件。
MyWindow obj = new MyWindow();
obj.ShowDialog();
obj.Close();
【问题讨论】:
在我的 WPF 应用程序中,我创建了一个窗口并通过 ShowDialog() 方法调用它以将其显示为对话框。但是当我通过 Close() 方法关闭窗口时,不会为此对话框窗口触发 Unloaded 事件。
MyWindow obj = new MyWindow();
obj.ShowDialog();
obj.Close();
【问题讨论】:
这是一个已知问题。
改用这个
yourWindow.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
private void Dispatcher_ShutdownStarted( object sender, EventArgs e )
{
//do what you want to do on closing
}
阅读this了解更多详情
编辑
如果上面的方法不起作用,试试这个
yourWindow.Closing += new CancelEventHandler(YourWindow_Closing);
void YourWindow_Closing(object sender, CancelEventArgs e)
{
}
【讨论】:
如果您真的想确认关闭,我认为最好了解窗口的生命周期及其引发的相关事件。
但在我看来,最好的确认来源是Closed 事件。其他框架方式可能不可靠
当一个窗口关闭时,它会引发两个事件:Closing 和 Closed。
关闭在窗口关闭之前引发,它提供了一个 可以防止窗口关闭的机制。一个常见的原因 防止窗口关闭是如果窗口内容包含修改的数据。 在这种情况下,可以处理 Closing 事件来确定 数据是否脏,如果是,询问用户是否 继续关闭窗口而不保存数据或取消 窗户关闭。下面的例子显示了关键方面 处理收尾。
更多
Closing 事件处理程序被传递一个 CancelEventArgs,它 实现您设置为 true 的 BooleanCancel 属性以防止 从关闭的窗口。 +
如果关闭未处理,或已处理但未取消,则 窗口将关闭。就在窗口实际关闭之前, Closed 是 提高。此时,无法阻止窗口关闭。
注意
虽然窗口可以通过提供的机制显式关闭 非客户区和客户区,一个窗口也可以是隐式的 由于应用程序其他部分的行为而关闭或 Windows,包括以下:
用户注销或关闭 Windows。
窗口的所有者关闭。
主应用程序窗口关闭,ShutdownMode 为 OnMainWindowClose。
已调用关机。
下图显示了窗口生命周期中主要事件的顺序。
下图显示了在未激活的情况下显示的窗口生命周期中主要事件的顺序(在显示窗口之前将 ShowActivated 设置为 false)。
【讨论】:
我偶然发现了这个变通方法。我碰巧在我的代码中创建了另一个窗口,因此没有看到在 WPF 中未触发 Unloaded Event 的问题。
public partial class Window1 : Window { public Window1() { InitializeComponent(); new Window(); //<-- this will make Unloaded Event to trigger in WPF } }
解决方法也适用于 MVVM 模式!
如果您不使用 MVVM 模式,请忽略下面的其余代码。
XAML
(需要参考 System.Windows.Interactivity)
<Window xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"> <i:Interaction.Triggers> <i:EventTrigger EventName="Unloaded"> <i:InvokeCommandAction Command="{Binding Path=DataContext.WindowUnLoadEventHandler,RelativeSource={RelativeSource AncestorType {x:Type Window}}}"/> </i:EventTrigger> </i:Interaction.Triggers> </Window>
后面的代码
public ICommand WindowUnLoadEventHandler { get { if (_windowUnload == null) { _windowUnload = new MyDelegateCommand(ExecuteWindowUnLoadEventHandler); } return _windowUnload; } } private void ExecuteWindowUnLoadEventHandler(object parameter) { //Do your thing }
MyDelegateCommand
public class MyDelegateCommand : ICommand { private readonly Action<object> _execute; public MyDelegateCommand(Action<object> execute) { this._execute = execute; } public void Execute(object parameter) { _execute?.Invoke(parameter); } public bool CanExecute(object parameter) { return true; } public event EventHandler CanExecuteChanged; }
【讨论】: