Following this example, https://learn.microsoft.com/en-us/windows/uwp/design/layout/show-multiple-views If I open any view in a secondary view, the Unloaded event of the Page opened in the Secondary Window never gets called. So there are many objects that are left without disposing properly, as I have some cleanup code in the Unloaded event.
I know that I can use the Consolidated event in the view to know when the secondary view is closed (Because the Closed event never gets called in the Window) But I cannot use this as I have some custom buttons that need to be unloaded before closing the secondary views. I can make some dirty patches but I want to avoid this. Any thoughts?
But I cannot use this as I have some custom buttons that need to be unloaded before closing the secondary views.
The unloaded event will not be fired when you close the window. I did not understand why you could not use the Consolidated event. According to your description, you just want to do some clean operation before the window is closed. The ApplicationView.Consolidated Event occurs when the window is removed from the list of recently used apps, or if the user executes a close gesture on it. It exactly meets your requirement.
You could check the official MultipleViews sample. It implements a ViewLifetimeControl.cs to control your secondary views and implements the release events and relevant functions to keep track of the secondary views and destroying the objects when closing.
Related
My problem is that I want to know when the user navigated to the page and when navigated away. So I can perform some page specific tasks like subscribing and unsubscribing to events.
Previously it was obvious and we could override OnNavigatedTo and OnNavigatingFrom methods. But in Windows Phone Runtime, there is no guarantee those methods occur when the user switches between apps for example.
In Windows Phone Runtime, how to know when the user is opening a page and when going away (to another page, start screen or another app)?
When you navigate to another page - it's simple, you handle NavigatingFrom/NavigatedTo. When not - it's also simple - you shouldn't be getting these events and so you should do nothing in most cases. I've seen NavigatingFrom being raised though in certain circumstances when the app was getting suspended and navigation state was being read from the Frame even though technically in-app navigation wasn't occurring and there would be no matching NavigatedTo event on resume. You might want to filter that out by setting and clearing some flag in the Suspending event (or Application.OnSuspending override) before and after NavigatingFrom is triggered and then ignoring it in the page NavigatingFrom handler for certain code. You would probably still want to save the page state in that event, but not unsubscribe from other events in case the app gets resumed before it gets terminated.
Application.Suspending/Resuming are some events you might also be interested in for saving/loading overall app state or refreshing data, though maybe less so for subscribing/unsubscribing from events since most of these should be fine to leave alone when the app gets suspended which happens when you switch to another app.
Page.Loaded/Unloaded events are ones you would handle if you want to touch parts of the UI that need to actually be loaded in the visual tree, since NavigatedTo happens before the page is loaded.
I know that in Desktop apps we have things like Form_Closing which is great for doing stuff before the app shuts down, but I need to do things before a Metro app shuts down (is closed by the user or the system) and I can't get this working.
The only events that seem to be even remotely related are the App_Suspending and pageRoot_Unloaded events.
My problem is that my code (any code at all) never gets called if I put it in the Unloaded event, which makes me believe that the Unloaded event never gets fired.
I haven't tried using the Suspending event yet because I need to do this work when the app is actually closing, or about to be closed, not just suspended.
Any ideas?
There is no diff between Closing and Suspending Metro App on the moment of suspending, so you must save state in OnSuspending override every time. But after re-Activating you can see what was happened with your App (OnLaunched (for example, here you can see value ClosedByUser)).
Here is not bad article about WinRT LifeCycle.
you can override OnNavigatedFrom method which will be invokved when page is being navigated away from.
http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.controls.page.onnavigatedfrom.aspx
I dont think there is any explicit calls for app being terminated (accept checking the previous state in app.xaml.cs)
I added a code for standard "Are you sure you want to exit?" message inside the this.Closing
event of my main window.
It works as expected for closing from the gui, however I would like to disable this check when the application is closed via Application.Shutdown().
There is no event in the Application fired before the window gets closed and the Shutdown method cannot be overriden.
How can I detect what invoked the closing of the window?
Disclaimer: I'd make this a comment rather than an answer if I could as it is a dirty hack (not a clean one). But if you really need something and no better solutions present itself I'll post it anyway to hopefully help...
If you're definitely not in a position to control / hook the parts of the code base that are calling application shutdown, then the possibility is to find something else that responds to the shutdown that you can trip before your window closes.
My (not so ideal) thought on that is to set up another hidden window (SO: Loading a WPF Window without showing it) that the user wont interact with but the application will close on shutdown.
In the closing event of that window you can set a flag to indicate the application is shutting down. Then in your main window's closing event you can react to that flag.
The big issue to tackle is configuring things so that the hidden window will always close before the Main Window(s) safely.
I did some limited tests with MainWindow.Xaml as the application Startupuri, and creating the hidden window from the application.onstartup event and found the hidden window would close first - but I wouldn't want to gaurantee that in all scenerios! Actually getting this working and tested adequately could be a lot of work - as I said it's a last restort dirty hack.
Who calls Application.Shutdown()? If you are in Charge of that just set a flag indicating that you did it and check for that flag in the Closing event handler.
I'm currently working on an application that uses a Windows Form GUI. The main work of the application will be performed on an additional thread - but it is possible that it will be dependent on the state of the form.
Because of this, before I create the thread I must make sure that the form is completely loaded. Also, I need to make sure the thread is terminated before the form begins closing.
Possible solutions for this problem might be overriding the OnShown and OnFormClosing methods.
Does the OnShow method really gets called only after ALL of the assets of the form have been loaded? And what about the OnFormClosing - can I be sure that any code executed in this method will be performed before the form begins close / dispose?
I suggest you read through the WinForms event ordering as posted on MSDN:
http://msdn.microsoft.com/en-us/library/86faxx0d.aspx
Windows Forms events can be tricky, and the order they fire unreliable. For example, the 'Shown' event is meant to fire once and once only, when the Form is first displayed, but just yesterday I found a way to completely prevent that event from firing by manipulating Form.Visible flags at the right time.
So, you need to be quite specific about your needs. For example - when you say 'completely loaded', what do you mean? Controls created, form visible, Form constructor finished executing?
Likewise, the FormClosing event might be circumvented by an unhandled exception in your main aUI thread, which results in the Form being removed without the event firing.
I suggest never assuming anything around these events. Make your worker thread capable of dealing with the Form state being unavailable, or not ready. Without knowing your exact requirements, it's hard to be more specific.
Have you tried to use InitializeComponent on the constructor of your main WinForm and use OnLoad (called whenever everything is loaded)?
My basic issue is this, I have events firing on pages I've left based on network activity that are causing problems when I thought the old forms were being destroyed.
More detailed information: I am writing a windows phone app that communicates with a network player. I have a static instance of my communication class in my App class so all the forms can share the connection, and all my forms subscribe to it and process results within that form. From a main menu you can choose one type of source and it opens a file browsing form that refreshes a listbox as you navigate, cancels the back button and refreshes the new contents to simulate file navigation until you are the root folder. The app doesn't know if you're clicking on a file or folder, it gets a network message when media starts playing and watch for that and then navigate to a "play" form. I had been using all .Navigate's for this until now and it worked great until I added another branch off the main menu for a new source. Although the new source is completely different, the device sends a lot of the same generic commands which just mean something else in the current context. After visiting the my file browser form and going to my new source, a play command from the network, which means something else now, would cause my to jump into my old "play" form from the previous source as if I was still on the file browser form, which isn't intended.
So I've tried many things and have it kind of working now but it's message and I lose some features. Currently I changed from using all .navigates, also in the back button override, to trying to use the stack and navigate.goback's. I pass variables when needed using globals in App and unhook my net listeners from the form, goback, and then connect them in the new form's listeners in it' navigatedto. I think there is timing issue though as in some cases I needed to send a command to the media box as it's changing and it ended up triggering the wrong event handler again. I think the easiest solution, if possible, and they way I though it would work is if each time I navigated from the form it old one, it's handlers, etc were all destroyed and I didn't have to use the stack at all, handling all the back buttons myself.
I know that's a long description and thanks if you made it this far, hopefully it made some kind of sense. Does anyone have any suggestions on what I can do?
As a side note I'm a long time self-taught VB programmer who has been stuck in .net 2.0/winforms and I've just now made the move to C#, OOPs, and XAML to write my first Windows Phone app so it's likely I'm doing something stupid or overlooking something obvious...
It is likely because something has retained reference to the form. The most common cause is event handlers.
So, if your static class exposes an event, and you subscribe to that event in a form, you must unsubscribe from the event when your form closes / navigates, otherwise the form will remain in memory....
If that isn't the case, look for something else that is acquiring a reference to your form and not releasing it.
Most likely the problem is based on a bad application architecture, when it comes to handling commands send from the UI.
When you say 'sends a lot of the same generic commands which just mean something else in the current context.' you most likely reveal the source of the problem.
As a workaround, you can define an interface, that your communication class implements. Each form has it's own method it calls on a communication class instance.
If you indeed receive a command from a phone page, that is no longer in view, just don't process it.
You can store the navigation history to always know what page is the only one allowed to send commands to a communication class.