UWP Page.OnNavigatedFrom() not called when app is terminated - c#

I've overridden the Page.OnNavigatedFrom() method in a UWP app. The method is called when I navigate to another Page. According to the documentation, Page.OnNavigatedFrom() is:
Invoked immediately after the Page is unloaded and is no longer the
current source of a parent Frame.
However, when I terminate the app, the Page's OnNavigatedFrom() is not called. Shouldn't terminating the app unload the Page?
// Not called when app is terminated
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
}
Update
I appreciate the comments. To be more clear, I should have said that I was closing the app, not terminating the app. (Closing the app first suspends and then terminates the app.) I discovered that putting a call to Frame.GetNavigationState() in OnSuspending() caused OnNavigatedFrom() to be called even when the user closes the app:
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
// Triggers currently loaded Page's OnNavigatedFrom
Frame frame = Window.Current.Content as Frame;
ApplicationData.Current.LocalSettings.Values["NavigationState"] =
frame.GetNavigationState();
deferral.Complete();
}

Invoked immediately after the Page is unloaded and is no longer the current source of a parent Frame
I think you misunderstood the document. OnNavigatedFrom() method will invoked when page unloaded and is no longer the current source of frame. It is page life cycle only available in the scenario of navigation stack.
But, terminate is the app life cycle concept. and its priority is higher than the page life cycle.
When you terminate uwp app, OnSuspending event handler will be invoked, if you want to save page data, you could subscribe this event in page class.

Related

How do I use the event VisibilityChanged?

I need to re-run the code contained within dela method OnNavigatedTo () when the app resumes from background.
To do this I need the event VisibilityChanged:
Link MSDN
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
//My code
}
With this event, each time the app is opened again from the background, the code contained within dell'OnNavigatedTo runs again. How can I use that event? I can not.
Visibility changed is only relevant if the page isn't in the background. Every time the app opens it goes to OnNavigatedTo(), you can make a bool or counter to check if it is the first time you entered the page and then decide what to do based on that inside OnNavigatedTo. for Example:
private override void OnNavigatedTo(NavigationEventArgs e)
{
if(hasBeenHere) Repeat_Visit(args);
else First_Visit(args);
}
The Application_Activated Event gets fired when the application is resumed from the background.
From the App.xaml.cs of the WP8.1 Template:
// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
// your code
}
Edit : to call methods on MainPage from app.xaml.cs has already been answered here : How to use a method in MainPage from app.xaml.cs with variable appbar pivot

Delay while loading WPF page

I have a Button on Page 1 and on Button_click Doing some operations with a background worker and showing the progress and once the operation is finished , application
loads a new page like this
Uri ViewPageUri = new System.Uri("View.xaml", UriKind.Relative);
private void bookOpeningWorker_WorkFinished(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
NavigationService.Navigate(ViewPageUri);
}
}
Inside View Page Loaded event doing some other time consuming operations in a Background worker and showing the waiitng progress.
The second page contains few user controls and some other browser controls , but all the operations are performing on Load event of the page
All things are working fine , but the only issue is application is taking some time to finish execution between the lines NavigationService.Navigate and Loaded event of the Page
So i am getting a delay of 3-4 seconds betweeen this time and no progress or waiting messages are visible to end user and also i can see the pointer in a waiting mode .
Is there any specific reason for this effect?or any better way to improve the code?

OnNavigatedFrom is not called when the app is suspended

Today I've encountered strange problem - seems that on my device (v. 8.10.14203.306) OnNavigatedFrom event is not getting called when the app is being suspended. As far as I remember some time ago it was working ok, and exacly as documentation stays:
Note On Windows Phone, OnNavigatedFrom() is called when the app is suspended. OnNavigatedTo() is not called when the app is resumed.
I've tried a simple example (available at GitHub):
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedFrom(e);
Debug.WriteLine("Navigation");
this.Background = new SolidColorBrush(Colors.Red);
}
when there is normal navigation (e.g. by back button) the event is fired, but no more when the app is suspended - both in debug and release mode. I've also checked if the Suspending event is fired and it turnes out that it is:
// uncomment this to check if app is being suspended
App.Current.Suspending += (sender, e) => this.Background = new SolidColorBrush(Colors.Blue);
Am I missing something?
The only thing I can suggest is to make sure that you're calling Frame.GetNavigationState from within your Application.Suspending handler (this is usually done by SuspensionManager.SaveAsync). According to the docs:
Calling this method will call Page.OnNavigatedFrom for the current page using NavigationMode.Forward. GetNavigationState is usually called when the application is being suspended, so the current page is navigated away from.

Capture Activated event for an App

I am referring to http://msdn.microsoft.com/en-us/library/windows/apps/hh464925.aspx#app_activation
// App is an Application
public App()
{
this.InitializeComponent();
// Doesn't compile
//this.Activated += OnActivated;
this.Suspending += OnSuspending;
}
protected override void OnActivated(IActivatedEventArgs args)
{
System.Diagnostics.Debug.WriteLine("OnActivated");
}
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
deferral.Complete();
}
Note, OnActivated will never be triggered. OnSuspending will be triggered, after I quit the app around 30 seconds.
How can I capture Activated event? It is weird that I do not find Activated event in App, although the documentation says so.
The activation is a little confusing. Take a look at the documentation here:
http://msdn.microsoft.com/en-us/library/windows/apps/br242324.aspx
What you'll find is that when the user taps the tile, only the OnLaunched event is fired (see documentation here: http://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.application.onactivated.aspx )
The OnActivated is only for special cases outside of the ordinary launch. That would be any one of the following:
OnFileActivated
OnSearchActivated
OnShareTargetActivated
OnFileOpenPickerActivated
OnFileSavePickerActivated
OnCachedFileUpdaterActivated
So if you truly want something that is called anytime the app is activated regardless of how, I'd suggest making your own private method, then calling it from both OnLaunched and OnActivated. That should hit all cases for activation.
Maybe the problem is that you launch the app normally for example, by tapping the app tile(without facts, I'm just guessing). In this case, only the OnLaunched method is called.
msdn

Detect WebBrowser complete page loading

How can I detect when a System.Windows.Forms.WebBrowser control has completed loading?
I tried to use the Navigate and DocumentCompleted events but both of them were raised a few times during document loading!
I think the DocumentCompleted event will get fired for all child documents that are loaded as well (like JS and CSS, for example). You could look at the WebBrowserDocumentCompletedEventArgs in DocumentCompleted and check the Url property and compare that to the Url of the main page.
I did the following:
void BrowserDocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
return;
//The page is finished loading
}
The last page loaded tends to be the one navigated to, so this should work.
From here.
The following should work.
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//Check if page is fully loaded or not
if (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete)
return;
else
//Action to be taken on page loading completion
}
Note the url in DocumentCompleted can be different than navigating url due to server transfer or url normalization (e.g. you navigate to www.microsoft.com and got http://www.microsoft.com in documentcomplete)
In pages with no frames, this event fires one time after loading is complete. In pages with multiple frames, this event fires for each navigating frame (note navigation is supported inside a frame, for instance clicking a link in a frame could navigate the frame to another page). The highest level navigating frame, which may or may not be the top level browser, fires the final DocumentComplete event.
In native code you would compare the sender of the DocumentComplete event to determine if the event is the final event in the navigation or not. However in Windows Forms the sender parameter is not wrapped by WebBrowserDocumentCompletedEventArgs. You can either sink the native event to get the parameter's value, or check the readystate property of the browser or frame documents in the DocumentCompleted event handler to see if all frames are in the ready state.
There is a prolblem with the readystate method as if a download manager is present and the navigation is to a downloadable file, the navigation could be cancelled by the download manager and the readystate won't become complete.
I had the same issue of multiple DocumentCompleted fired events and tried out all the suggestions above. Finally, seems that in my case neither IsBusy property works right nor Url property, but the ReadyState seems to be what I needed, because it has the status 'Interactive' while loading the multiple frames and it gets the status 'Complete' only after loading the last one. Thus, I know when the page is fully loaded with all its components.
I hope this may help others too :)
It doesn't seem to trigger DocumentCompleted/Navigated events for external Javascript or CSS files, but it will for iframes. As PK says, compare the WebBrowserDocumentCompletedEventArgs.Url property (I don't have the karma to make a comment yet).
If you're using WPF there is a LoadCompleted event.
If it's Windows.Forms, the DocumentCompleted event should be the correct one. If the page you're loading has frames, your WebBrowser control will fire the DocumentCompleted event for each frame (see here for more details). I would suggest checking the IsBusy property each time the event is fired and if it is false then your page is fully done loading.
Using the DocumentCompleted event with a page with multiple nested frames didn't work for me.
I used the Interop.SHDocVW library to cast the WebBrowser control like this:
public class webControlWrapper
{
private bool _complete;
private WebBrowser _webBrowserControl;
public webControlWrapper(WebBrowser webBrowserControl)
{
_webBrowserControl = webBrowserControl;
}
public void NavigateAndWaitForComplete(string url)
{
_complete = false;
_webBrowserControl.Navigate(url);
var webBrowser = (SHDocVw.WebBrowser) _webBrowserControl.ActiveXInstance;
if (webBrowser != null)
webBrowser.DocumentComplete += WebControl_DocumentComplete;
//Wait until page is complete
while (!_complete)
{
Application.DoEvents();
}
}
private void WebControl_DocumentComplete(object pDisp, ref object URL)
{
// Test if it's the main frame who called the event.
if (pDisp == _webBrowserControl.ActiveXInstance)
_complete = true;
}
This code works for me when navigating to a defined URL using the webBrowserControl.Navigate(url) method, but I don't know how to control page complete when a html button is clicked using the htmlElement.InvokeMember("click").
You can use the event ProgressChanged ; the last time it is raised will indicate that the document is fully rendered:
this.webBrowser.ProgressChanged += new
WebBrowserProgressChangedEventHandler(webBrowser_ProgressChanged);

Categories