10

In my WPF application I have created a window and show it as a dialog by calling it by the method ShowDialog(). But when I close the window by Close() method the Unloaded event is not fired for this dialog window.

MyWindow obj = new MyWindow(); 
obj.ShowDialog();
obj.Close();
tshepang
  • 12,111
  • 21
  • 91
  • 136
HotTester
  • 5,620
  • 15
  • 63
  • 97

3 Answers3

15

That's a known issue.

Use this instead

   yourWindow.Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;

   private void Dispatcher_ShutdownStarted( object sender, EventArgs e )
   {
       //do what you want to do on closing
   }

Read this for more details

Edit

If above is not working try this

yourWindow.Closing += new CancelEventHandler(YourWindow_Closing);

void YourWindow_Closing(object sender, CancelEventArgs e)
{

}
Haris Hasan
  • 29,856
  • 10
  • 92
  • 122
  • 1
    This event too is not firing after obj.Close(). It is only firing when the whole application is closed. – HotTester Jan 18 '12 at 10:16
  • Yes. I have created Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted; in the constructor of the dialog window and written its event in the function as given above. – HotTester Jan 18 '12 at 10:21
  • 1
    Yes the updated answer is working ! For it we have to use System.ComponentModel. Thanks :). But I still wonder why did not the Window.Unloaded() or Dispather.ShutdownStarted() did not work. Is it because the window was used as dialog ? – HotTester Jan 18 '12 at 10:47
  • 1
    I am still confused about this behaviour but on googling I found ou people suggest going for closing event to be on safe side. Unloaded might be skipped in some cases. At this time I still don't know why – Haris Hasan Jan 18 '12 at 10:58
11

if you really want to get confirmation of closing i think its best to understand the life-cycle of a window and the relevant events it raises.

However the in my opinion the best source of confirmation is the Closed Event. Other framework ways maybe unreliable

Closing Events

When a window closes, it raises two events: Closing and Closed.

Closing is raised before the window closes, and it provides a mechanism by which window closure can be prevented. One common reason to prevent window closure is if window content contains modified data. In this situation, the Closing event can be handled to determine whether data is dirty and, if so, to ask the user whether to either continue closing the window without saving the data or to cancel window closure. The following example shows the key aspects of handling Closing.

Further more

The Closing event handler is passed a CancelEventArgs, which implements the BooleanCancel property that you set to true to prevent a window from closing. +

If Closing is not handled, or it is handled but not canceled, the window will close. Just before a window actually closes, Closed is raised. At this point, a window cannot be prevented from closing.

Note

While a window can be explicitly closed through mechanisms provided in the non-client and client areas, a window can also be implicitly closed as a result of behavior in other parts of the application or Windows, including the following:

  • A user logs off or shuts down Windows.

  • A window's owner closes.

  • The main application window is closed and ShutdownMode is OnMainWindowClose.

  • Shutdown is called.

All Window Lifetime Events

The following illustration shows the sequence of the principal events in the lifetime of a window.

enter image description here

The following illustration shows the sequence of the principal events in the lifetime of a window that is shown without activation (ShowActivated is set to false before the window is shown).

enter image description here

TheGeneral
  • 79,002
  • 9
  • 103
  • 141
0

I stumbled on this work-around by accident. I happened to create another window in my code and therefore did not see the issue of Unloaded Event not firing in WPF.

public partial class Window1 : Window
{
    public Window1()
    {
        InitializeComponent();

        new Window(); //<-- this will make Unloaded Event to trigger in WPF
    }
}

The work-around also works in MVVM pattern!

Ignore the rest of the code below if you don't do MVVM pattern.

XAML (Requires reference to 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>

Code behind

    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;
}
icernos
  • 395
  • 3
  • 6
  • 1
    Unfortunately this works only because creating a window instance will add it as "open" window of the app and therefore the app will not close properly – Martin Zikmund Oct 03 '19 at 15:36