Content UserControl is unloaded when switch tab, float ToolWindow...

Docking/MDI for WPF Forum

Posted 4 years ago by torick
Version: 15.1.0621
Avatar

I am using Livet, an MVVM infrastructure, where custom UserControls dispose their DataContext when they are Unloaded.

The problem is, as written in title, content UserControl's Unloaded event is fired when handling the container ToolWindow, which will currpt the UserControl on later use.

Is there any neat way to prevent this problem?

EDIT:

I know this post: http://www.actiprosoftware.com/community/thread/4638/why-unloadingloading-during-move#17116

It's been several years, and any newer work around is appreciated.

[Modified 4 years ago]

Comments (6)

Posted 4 years ago by torick
Avatar

I have made up a workaround:

  1. Make a public static class to switch disposablity.
  2. Override Dispose(), which does not call base Dispose() when the static class does not allow it, for all the view models.
  3. Add a delegate to ToolWindow.RequestBringIntoView event that disables dispose.
  4. Add a delegate to ToolWindow.Content.Loaded event that enables dispose (Dispose() is called between these two events).

It is working fine so far.

[Modified 4 years ago]

Posted 4 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hello,

As mentioned in the other post, the Loaded/Unloaded events of controls is raised internally by Microsoft's WPF control and as such, we don't really have a way to block those for layout change scenarios like tab switches, floats, other hierarchy changes, etc.

Your best bet is to watch the DockSite.WindowClosed event and when appropriate (perhaps only for document windows?), dispose the DataContext of the docking window's child UserControl from there.  That will be the most reliable way of knowing when a control is no longer in the layout and I would recommend it over what you are doing now.


Actipro Software Support

Posted 2 years ago by Nick Waanders
Avatar

Hi,

I am looking into a similar problem with version 2017.1 build 0652. I've got my own class derived from DocumentWindow that is showing some content that should get disposed when the DocumentWindow is destroyed (not when it's hidden in a tab). I can't use the unloaded event, since that is called when changing tabs in the MDI container.

This dispose call should get called the moment the document actually closes, and preferably inside my DocumentWindow class, so I was hoping to just hook into a 'DocumentWindow.Destroyed' event, but that doesn't seem to exist unfortunately.

Is the method of hooking into the DockSite.WindowClosed event and determining whether the content inside the document needs to be disposed still the way to go? It seems like a roundabout way of doing this. I'm trying to understand why, is there a reason for this?

Cheers,

Nick

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Nick,

When a docking window is "closed," it has been removed from the layout altogether.  Meaning it's not in any tabs, etc.  It is still alive in the DockSite though, waiting to possibly be reopened. 

When a docking window is "destroyed," it has been closed and also unregistered from the DockSite.  Document windows (by default) auto-destroy themselves when they are closed since their lifetime typically end when they are closed.  Tool windows do not auto-destroy when closed since they are intended to reopen again later.

All our events are centralized on the DockSite at this time, which generally makes it easier to handle when you have any number of multiple docking windows.  So yes, what you would do is handle the DockSite.WindowUnregistered event, which fires when a docking window is destroyed.  And in that handler you could dispose your content for the specified docking window.

We are open to making API enhancements in the future, so if you have any suggestions on API additions that would help, please send them over.


Actipro Software Support

Posted 2 years ago by Nick Waanders
Avatar

Hi,

No problem, I will use the suggested method. I've moved my destroy-code from the WindowsClosed to the WindowUnregistered event, which works well. In my case I guess there's not much of a difference, as I was using the setting where documents destroy themselves when they close. But, WindowUnregistered seems like the better place. 

As for API enhancements, the above isn't really that hard to implement, so it's probably ok as-is. I guess intuitively I was looking for a virtual function to override or an event to hook into inside my document class (derived from DocumentWindow) for the destroy, or 'this window is really gone now' event.

I think this is because I was thinking of MDI Documents as regular windows (which have a Closed event in regular WPF), rather than controls (which don't have a Closed event, unfortunately imho)

Thanks for your clarifications and help!

Cheers,

Nick

Posted 2 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi Nick,

One thing you could do if you inherited DocumentWindow is to override its OnDockSiteChanged method.  That would fire any time a docking window is registered and/or unregistered from a DockSite.  So if a docking window is destroyed, it effectively gets unregistered from the DockSite and OnDockSiteChanged(oldDockSite, null) is effectively called.


Actipro Software Support

The latest build of this product (v2019.1 build 0681) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.