Trying to understand closed widgets or Where "closed" widgets goes? - qooxdoo

I'm trying to archive a closable Composite custom widget. I'm studying the Window, Page and TabView classes.
The close() method from Window basically just hide the widget, The TabView listen for close Page event, then call to remove(page) method, this remove the page from the internal pane, but i don't found a kind of page.close(). So, what happened with closed widows and Pages? Still exist?
My own close() method must just call to hide() method and fire a close event just like Window does? This do not carry some memory leaks?

Widgets stay usable until you call widget.destroy(), but until then you are free to either hide them or remove them from their parent container. Once they have been removed from one container, you can reuse them and add them to another container altogether - in the days of IE6 this was a common requirement because it was faster to move unused widgets into a pool and reuse them than to create a new one from scratch (the widget will retain it's DOM elements until it is destroyed).
The close() method in Window is really just part of the semantics of using a Window - all it really does is remove or hide the Window widget and fire an event, so close() and open() are (almost) nothing more than nice API sugar to make life easy for the user.
OTOH Page doesn't need a close() method because adding and removing pages from the TabView is the entire concept.

Related

How to dispose of dynamically loaded usercontrols/viewmodels when parent window is closed

We have a main window that launches a child window. That child window dynamically loads custom usercontrols. In the contructor of these usercontrols, I pass a master object which, from this master object, a usercontrol specific viewmodel is generated and assigned as its datacontext.
All of this is working quite well. However, I jst discovered that when I close the child window at least some of my custom usercontrols are still active. How am I supposed to clean up my controls/viewmodels? Nothing seems to get called until the main window is closed. No destructor, no Dispatcher.ShutdownStarted, no dispose is available, no closing event, nothing I can find.
Anyone know what is supposed to be done to properly clean up after the window is closed?
I believe you need to think precisely about what is responsible for creating your views and your viewmodels, and what is responsible for determining whether or not something can close or not, etc.
It is usually a good idea for whatever that created something to destroy it. Therefore, if your child window is creating custom user controls it perhaps should be responsible for removing them. However, I believe if none of your objects has a reference (or strong event subscription) it should be eventually garbage collected. You could implement a finalizer/destructor and output a Debug.String to the output window to see when this might eventually happen. A good memory profiler could also be a good idea. However, it is also likely that you need more precise control of telling your ViewModel when it has been closed.
It's hard to say exactly what should happen in your scenario because it really depends on your exact and specific setup. Let me describe to you a scenario I had in my application. I had several views that were being displayed in tab pages. The tab pages had an X button to close the tab, and my View contained a hosted Windows Forms control that needed to have .Dispose() called to clean up resources as well as it needed to be informed of when to unsubscribe from composite commands in the file menu system. So, initially, I had a problem... how does my ViewModel unsubscribe from commands when the tab pages remove's the view? How does the View which is contained in a WPF control know when it has been removed? here's what I came up with
The tab page itself should not be telling my program if a view can or can not be closed
I needed the ability to cancel the closing event in case of program logic (File saved? Yes/no/cancel)
I needed the ability to detect when it was closed so I could cleanup/unregister at that exact moment
My solution was to implement an interface in my viewmodel called IRemovable which exposed a Removable boolean and a Remove() method which returns a boolean (was removed or not). My tab control only displayed the X button if Removable was true, Tab Control's Closing fired the Remove() of the IRemovable ViewModel and if it returned false it set the event args Canceled property to true if the ViewModel's Remove returned false.
Therefore, the remove of the view model could prompt the user for confirmation, unregister from commands, etc. The view could handle Closed event and call Dispose on any Windows Forms components etc. (of course I had to check if my View.DataContext is IRemovable).
Anyway, I know this isn't an exact answer but hopefully it helps you come up with some thoughts on how to solve your own problem

Disposing MDI Child forms

According to the msdn
The two conditions when a form is not disposed on Close is when (1) it
is part of a multiple-document interface (MDI) application, and the
form is not visible; and (2) you have displayed the form using
ShowDialog. In these cases, you will need to call Dispose manually to
mark all of the form's controls for garbage collection.
How do I go about this for the first case? If I manually dispose, this.dispose() ,of the form and set a breakpoint within dispose (found in the form's designer file), the breakpoint is never reached.
Start by not hiding MDI child windows, there's little point. If you really do need to hide them then call their Dispose() method instead of their Close() method. Dispose() will also close the window if it isn't hidden.

Recommended way to add/remove items from a Ext.Container in Sencha Touch 2?

I am optimizing my application. Originally, it's a Ext.TabPanel but I decided to use only a Ext.TabBar docked at the bottom and change the views above, so it requires a lot of add/remove actions from my main Ext.Container.
So my question is: in what way I should do to add/remove items from my Ext.Container effectively? I mean: fast, not cause memory-leaks, and also, not cause error like this: the view with a button in it, firstly added, all handlers (which are define through refs and control in a controller) work well but the second time (i.e it's removed and added again later), all handlers die.
Thanks in advance!
You have to ensure that you destroy the panel is destroyed otherwise it would be sitting in the dom.
Generally to remove a component from a container you use the Container remove() function which takes in the first parameter as the item to be removed and the second one is a boolean which instructs for it to be destroyed or not. You should ensure you set it to true to make sure you keep your DOM as lean as possible. Unless you're going to be reusing that component in the near future and do not want to render it again, then you do not need to destroy it.
http://docs.sencha.com/touch/2-0/#!/api/Ext.Container-method-remove

WPF Calling function in Page from "Master" Window

I have a button in a Window that needs to call a function in pages contained within a frame. The page inside the frame will change based on a navigation contained in the main Window, so I will know the current Page within the frame.
Can someone help with how to call function in frame pages?
If you wish to approach this from an MVVM perspective, you'll want to make sure you're not working with the actual view here, but the ViewModel abstraction of it. In that case, your parent Window is probably backed by a ViewModel that contains some sort of a collection that backs your pages in the frame/tab control/container of choice. In that case, the button should link to a command on your Window-backing ViewModel and use the selected item in the collection to access the function. If you do not have a direct reference in this fashion (for example loading in from another module or something for frame contents) you can also use EventAggregator from the Prism/CAL libraries and publish an event when the window button is pressed and set up your pages to receive that event and handle the call there. EventAggregator can be a slick way to handle cross-module logic in a clean way.

WPF parent-child window: binding reference problem

I have a WPF Window that open a modal child window to load some data. Both window have a own viewmodel, now I have this problem: after I close the child window it seems still running in background!
To close the child window I set DialogResult from viewmodel command; now, if I create a new data and then I edit it from parent window (with the child window closed before), the child window still capture the property changed event for the properties previously bind.
How can avoid this?
I would clear every reference with data when I close modal window. Which is the best practise to do it?
Ensure that you don't keep any references to your window, even an indirect one. One of the most common cause of leaks are events. If a window B is adding an event handler to an event of window A, B won't be released until A is also.
For example, if you're directly listening to property changes, you should use the Weak Event Pattern and replace all your += with a call to PropertyChangedEventManager.AddListener. In general, every strong handler you add to an event should be removed to avoid leaking.
More information about leaks in .NET in this MSDN article.
You can use a memory profiler like Scitech's mem profiler or Jetbrains dotTrace to see what ojects are keeping your windows in memory.
Edit: In response to your comments, your case is really simpler than I first thought: the Garbage Collector simply didn't collect the window yet. Adding GC.Collect on Test_Click for testing purposes solves the issue.
Here, remove the SelectionChanged event from the ComboBox when the form is closing so you can let the GC do its job and reclaim the form later without having problems. If you really need the whole form to get released right now, you might consider calling GC.Collect although you should avoid it when you can.
Edit 2: In response to your third comment, it should only matters for objects that are shared between views, and where the changes in the view will change something back in a shared object. In your test project the SelectionChanged does nothing on the original list so it doesn't really matter if the event is raised or not. The form will get collected eventually.

Resources