在我的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
}
阅读这里以获取更多详细信息。
编辑
如果上述方法不起作用,请尝试这个。
yourWindow.Closing += new CancelEventHandler(YourWindow_Closing);
void YourWindow_Closing(object sender, CancelEventArgs e)
{
}
如果您真的想要确认关闭,我认为最好先了解窗口的生命周期和相关事件。
然而,在我看来,最好的确认来源是"Closed"事件。其他框架的方式可能不可靠。
当窗口关闭时,它会触发两个事件:Closing和Closed。
Closing在窗口关闭之前被触发,并提供了一个机制来防止窗口关闭。防止窗口关闭的一个常见原因是窗口内容包含已修改的数据。在这种情况下,可以处理Closing事件来确定数据是否有更改,并询问用户是继续关闭窗口而不保存数据还是取消窗口关闭。以下示例显示了处理Closing的关键方面。
此外
Closing事件处理程序会传递一个CancelEventArgs,它实现了BooleanCancel属性,您可以将其设置为true以防止窗口关闭。
如果没有处理Closing,或者处理了但没有被取消,窗口将关闭。在窗口实际关闭之前,Closed会被触发。此时,无法阻止窗口关闭。
注意
虽然窗口可以通过提供在非客户区和客户区的机制来显式关闭,但窗口也可以由应用程序或Windows的其他部分的行为隐式关闭,包括以下内容:
用户注销或关闭Windows。
窗口的所有者关闭。
主应用程序窗口关闭且ShutdownMode为OnMainWindowClose。
调用Shutdown。
下图显示了窗口生命周期中主要事件的顺序。
下图显示了一个未激活的窗口(在窗口显示之前设置ShowActivated为false)生命周期中主要事件的顺序。我偶然发现了这个解决方法。我在我的代码中创建了另一个窗口,因此没有看到 WPF 中未加载事件不触发的问题。
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
}
我的委托命令
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;
}