none
How can a method of a WPF Window find out if the Window is closed ?

    Question

  • My Window has an EventHandler which is added to an event in another class (EventSource). It can happen that the WPF Window is allready closed, but still in memory and the event gets raised. How can the EventHandler, which is a method of the Window, find out, if the Window is closed ? Accessing the window is easy, just use "this". But then ?

    Wednesday, January 02, 2008 7:28 AM

Answers

  • IsLoaded will be set to false when the Window is eligible for unloading its content, this will typically happens when you explicitly close the opened window, when IsLoaded sets to false, UnLoaded event will be triggered, this is consistent with how the Loaded event happens (first IsLoaded sets to true, then fire up the Loaded event).

    So Unloaded event will get fired if the Window is explicitly closed by the user (for instance click the "Close" button in the window's title bar), if the Window is implicitly closed (for instance when the application shuts down, all the opened windows will not have their Unloaded fired, if you want to change this behaviour, you can set the Application.Current.ShutDownMode to ShutDownMode.OnExplicitShutdown. In this way, you can get the Unloaded event fires for all the opened windows, but you need to explicitly call the Window.Close() to close all the opened windows, and finally call Application.Current.ShutDown() to shut down the application.

    As I've said several times in this thread, you can simply hook up to Window.Closed event, because unlike Unloaded event, this event will consistently be triggered whenever the window receives the WM_Close messages.

    I hope I've answered all your questions.
    Tuesday, January 08, 2008 3:19 AM
  •  Peter Huber wrote:

    Keeping track of the WPF windows state myself seems not the right thing to do (I explain later why). There surely must be a way how a WPF Window can find out if it is closed. This seems to be a very basic query !


    I am afraid the solution given by Alex should always be the right thing to do, even if in the world of WPF where weak event pattern is enabled. It's always a good practice to explicitly unsubscribe events when you are done with it.

     Peter Huber wrote:

    One possibility would be to use the WeakEventManager. But that one is ugly for many reasons:
    - the class listening to the event needs to implement IWeakEventListener. Yucks
    - the class listening to the event needs to derive its own WeakEventManager class for every event it uses. Big yuck !
    - the WeakeventManager is a complex piece of code, adding delay accordingly. Yucks



    I am sorry that the weak event pattern introduced by current version of WPF is a bit convoluted for you. But this pattern does solves the lifetime management issue of CLR objects when it comes to delegates/events, and this pattern is heavily used by WPF itself internally to implement change notifications for dependency property, data binding, visual/brush/transform change tracking etc etc. And I've posted a blog article on how to use this pattern, this might help you if you decide to use this pattern :
    http://shevaspace.spaces.live.com/blog/cns!FD9A0F1F8DD06954!471.entry

     Peter Huber wrote:

    - the WeakeventManager is not the proper solution. The right solution is that every Window subscribing to an event needs to unsubscribe as well.


    Agreed. weak event pattern is good in particular if the lifetime of those objects are hard to keep track of, because there are many circumstances from which you have no idea when or where a specified object will not be used, and eligible for disposing, so you cannot really figure out if this is the right time to unsubscribe the events, in those situtions, weak event pattern is good, it frees you from the nitty gritty stuff of how to track those lifetime management issues.

    In your situation, I think weak event pattern is not a good idea, since you know that when the window is closed, it should unsubscribe the events it registered, so Alex's solution shown above is a good way to do it in this respect.

     Peter Huber wrote:

    But how to guarantee that ? Just unsubscribe from the event in the window.closed event. But does Microsoft guarantee that the window.closed event is called for all windows ? In all circumstances ? Even when exceptions occur ? I couldn't find any such guarantee from Microsoft.


    I believe Window.Closed events will get fired in most circumstances except when exception occurs.
    I think if an exception is thrown when you close a window, you are free to catch the exception, and determine if it's recoverable, if it's recoverable, you can unsubscribe the events in the exception handler, and just simply let the application continue to run. You are actually responsible for this logic, because the WPF runtime has no way to figure out this for you.
    And if the exception is not recoverable, you can simply shut down the application or pop up a dialog to give the users option to either restart the application or shut down the application.

     Peter Huber wrote:

    If there is no guarantee, then I need to test, in run time, when the event is raised. If the Window is no longer referenced by anyone else, but the eventHandler is called, just remove the Window from the event and create an error, which will help us to analyse the code where we forgot to remove the eventHandler in the first place.


    This is an imaginary solution, the problem is that you have no idea if a Window is no longer referenced by anyone else except the event source, you might argue that the garbage collector should know about this, since it's has an object graph describing which object is still in use and which one is not, but that level of mechanism is not and will not be publicly exposed.






    Friday, January 04, 2008 3:34 AM

All replies

  •  

    add a field or propery bool Isclosed to the window

     

    in the window, add

    this.closed +=delegate(object sender, eventArgs){Iscolsed = true};

     

    in your handler,add

     

    if(this.Iscolsed )

       return;

    else

       do the task.....

     

     

    thanks

     

    Regards

    Wednesday, January 02, 2008 7:57 AM
  • Keeping track of the WPF windows state myself seems not the right thing to do (I explain later why). There surely must be a way how a WPF Window can find out if it is closed. This seems to be a very basic query !
     
    The problem I try to solve is to find out if an event is raised on a WPF form which should be garbage collected, but doesn't get garbage collected because the Window forgot to unregister from the event.
     
    One possibility would be to use the WeakEventManager. But that one is ugly for many reasons:
    - the class listening to the event needs to implement IWeakEventListener. Yucks
    - the class listening to the event needs to derive its own WeakEventManager class for every event it uses. Big yuck !
    - the WeakeventManager is a complex piece of code, adding delay accordingly. Yucks
    - the WeakeventManager is not the proper solution. The right solution is that every Window subscribing to an event needs to unsubscribe as well.
     
    But how to guarantee that ? Just unsubscribe from the event in the window.closed event. But does Microsoft guarantee that the window.closed event is called for all windows ? In all circumstances ? Even when exceptions occur ? I couldn't find any such guarantee from Microsoft.
     
    If there is no guarantee, then I need to test, in run time, when the event is raised. If the Window is no longer referenced by anyone else, but the eventHandler is called, just remove the Window from the event and create an error, which will help us to analyse the code where we forgot to remove the eventHandler in the first place.
     
    Much easier and neater than using the WeakEventManager, right ? But how can the eventHandler know that the WPF Window is no longer in use ?
     
    Setting a closed bool property in the Window.closed event is not the solution, because this is precisely the place where we should remove the eventhandler from the event. If the eventhandler was not removed, it can be because window.closed event never fired. Then, of course, the closed bool property wouldn't help at all.

    Thursday, January 03, 2008 1:45 PM
  •  Peter Huber wrote:

    Keeping track of the WPF windows state myself seems not the right thing to do (I explain later why). There surely must be a way how a WPF Window can find out if it is closed. This seems to be a very basic query !


    I am afraid the solution given by Alex should always be the right thing to do, even if in the world of WPF where weak event pattern is enabled. It's always a good practice to explicitly unsubscribe events when you are done with it.

     Peter Huber wrote:

    One possibility would be to use the WeakEventManager. But that one is ugly for many reasons:
    - the class listening to the event needs to implement IWeakEventListener. Yucks
    - the class listening to the event needs to derive its own WeakEventManager class for every event it uses. Big yuck !
    - the WeakeventManager is a complex piece of code, adding delay accordingly. Yucks



    I am sorry that the weak event pattern introduced by current version of WPF is a bit convoluted for you. But this pattern does solves the lifetime management issue of CLR objects when it comes to delegates/events, and this pattern is heavily used by WPF itself internally to implement change notifications for dependency property, data binding, visual/brush/transform change tracking etc etc. And I've posted a blog article on how to use this pattern, this might help you if you decide to use this pattern :
    http://shevaspace.spaces.live.com/blog/cns!FD9A0F1F8DD06954!471.entry

     Peter Huber wrote:

    - the WeakeventManager is not the proper solution. The right solution is that every Window subscribing to an event needs to unsubscribe as well.


    Agreed. weak event pattern is good in particular if the lifetime of those objects are hard to keep track of, because there are many circumstances from which you have no idea when or where a specified object will not be used, and eligible for disposing, so you cannot really figure out if this is the right time to unsubscribe the events, in those situtions, weak event pattern is good, it frees you from the nitty gritty stuff of how to track those lifetime management issues.

    In your situation, I think weak event pattern is not a good idea, since you know that when the window is closed, it should unsubscribe the events it registered, so Alex's solution shown above is a good way to do it in this respect.

     Peter Huber wrote:

    But how to guarantee that ? Just unsubscribe from the event in the window.closed event. But does Microsoft guarantee that the window.closed event is called for all windows ? In all circumstances ? Even when exceptions occur ? I couldn't find any such guarantee from Microsoft.


    I believe Window.Closed events will get fired in most circumstances except when exception occurs.
    I think if an exception is thrown when you close a window, you are free to catch the exception, and determine if it's recoverable, if it's recoverable, you can unsubscribe the events in the exception handler, and just simply let the application continue to run. You are actually responsible for this logic, because the WPF runtime has no way to figure out this for you.
    And if the exception is not recoverable, you can simply shut down the application or pop up a dialog to give the users option to either restart the application or shut down the application.

     Peter Huber wrote:

    If there is no guarantee, then I need to test, in run time, when the event is raised. If the Window is no longer referenced by anyone else, but the eventHandler is called, just remove the Window from the event and create an error, which will help us to analyse the code where we forgot to remove the eventHandler in the first place.


    This is an imaginary solution, the problem is that you have no idea if a Window is no longer referenced by anyone else except the event source, you might argue that the garbage collector should know about this, since it's has an object graph describing which object is still in use and which one is not, but that level of mechanism is not and will not be publicly exposed.






    Friday, January 04, 2008 3:34 AM
  • Hi Marco

     

    I'm honored by your answer and impressed how detailed it is. I have read your blog before and it was a great help to get the WeakEventManager running. The MSDN documentation is just not good enough. I also used Reflector to understand the inner working of the WeakEventManger. If I look at that code and consider how easy it would to be for the CLR to offer also weak events, I could cry. 

     

    Anyway, I came to the conclusion that using WeakEventManager is not the right solution, because I can check much earlier than the garbage collector if a window is still in use. Whenever my eventhandler in the WCP window is called, I can check if the Window is still open. If not, I remove the eventHandler from the event. An easy, elegant and performant solution, right ?

     

    But the eventhandler cannot querry the WPF Window if it is closed ? That is hard to believe. It sounds like such a basic property.

     

     

    PS: Of course, I didn't expect the garbage collector to tell me if the Window is still referenced. It seems Microsoft thinks the garbage collector is a magical solution (black box), that it is none of the developers business to investigate anything about it and Microsoft doesn't offer any classes for inspection during runtime and neither any tools to inspect garbage collector memory problems from Visual Studio. I read a blog from Microsoft how to investigate memory leaks. Horribly complicated.

     

    Friday, January 04, 2008 9:26 AM
  •  Peter Huber wrote:

    Anyway, I came to the conclusion that using WeakEventManager is not the right solution, because I can check much earlier than the garbage collector if a window is still in use. Whenever my eventhandler in the WCP window is called, I can check if the Window is still open. If not, I remove the eventHandler from the event. An easy, elegant and performant solution, right ?


    Agreed, weak event pattern is overkill in this situation as I've said that weak event pattern is useful if you have hard time tracking the lifetime of clr objects.

     Peter Huber wrote:

    But the eventhandler cannot querry the WPF Window if it is closed ? That is hard to believe. It sounds like such a basic property.


    Yes, it's indeed a basic property, and it's not so hard to implement this property yourself. WPF is still in its early stage, and it will be improving with the helpful feedbacks from customers like you and the hard work by our product teams

     Peter Huber wrote:

    Of course, I didn't expect the garbage collector to tell me if the Window is still referenced. It seems Microsoft thinks the garbage collector is a magical solution (black box), that it is none of the developers business to investigate anything about it and Microsoft doesn't offer any classes for inspection during runtime and neither any tools to inspect garbage collector memory problems from Visual Studio. I read a blog from Microsoft how to investigate memory leaks. Horribly complicated.


    In my personal opinion, the initial design goal of GC is freeing developers from the nitty gritty stuff of how to keep track of the lifetime of live objects. So it might be "understandable" that those underlying mechanism is locked in a black box.


    Friday, January 04, 2008 9:41 AM
  • I wonder if i could use the property FrameworkElement.IsLoaded. WPF Window inherits from FrameworkElement. When I just tried it out, IsLoaded was true when the Window.Loaded event gets raised. That is the time I add my EventListener. Once I closed the Window and raised the EventListener, IsLoaded is false.

     

    Of course, the MSDN documentation doesn't explain when isLoaded gets set to false. :-(

     

    Because of this lack of documentation, I have to ask here. Is it under all circumstances safe to assume that the Window is closed if isLoaded is false ? Of course, isLoaded is also false before the Window is loaded, but then the EventListener is not installed yet.

    Saturday, January 05, 2008 6:20 AM
  • IsLoaded will be set to false when the Window is eligible for unloading its content, this will typically happens when you explicitly close the opened window, when IsLoaded sets to false, UnLoaded event will be triggered, this is consistent with how the Loaded event happens (first IsLoaded sets to true, then fire up the Loaded event).

    So Unloaded event will get fired if the Window is explicitly closed by the user (for instance click the "Close" button in the window's title bar), if the Window is implicitly closed (for instance when the application shuts down, all the opened windows will not have their Unloaded fired, if you want to change this behaviour, you can set the Application.Current.ShutDownMode to ShutDownMode.OnExplicitShutdown. In this way, you can get the Unloaded event fires for all the opened windows, but you need to explicitly call the Window.Close() to close all the opened windows, and finally call Application.Current.ShutDown() to shut down the application.

    As I've said several times in this thread, you can simply hook up to Window.Closed event, because unlike Unloaded event, this event will consistently be triggered whenever the window receives the WM_Close messages.

    I hope I've answered all your questions.
    Tuesday, January 08, 2008 3:19 AM