How to finish current page in Windows Universal - windows

How can I close the current active Page in UWP development?
I want to start a new Page and close the current one, so the user cannot go back to that page.
Is there any method in UWP similar to Android's method "finish()"?

I think you should be able to do this by removing last page from back stack after navigating to a new one. Sample code in OnNavigatedTo of a new page:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
this.Frame.BackStack.RemoveAt(this.Frame.BackStack.Count - 1);
}
This should prevent user from going back to last page. Of course you can modifay the back stack in many ways if you need.

Related

Navigation.PushAsync(). When the back arrow is pressed the page seems to be still in memory

I am writing a Xamarin app. In the App.Xaml.cs I expose some events.
I set up a Main Page like this:
var nav = new NavigationPage(new MainPage());
MainPage = nav;
Then from the Main Page I push another page:
void DevicePictureBox_Click(object sender, EventArgs args)
{
Image imse = (Image)sender;
String NameofDevice =
devicesHandlesDictionary_byDevicepictureID[imse.Id].Name;
var p = new DevicesPage(NameofDevice);
Navigation.PushAsync(p);
The DevicesPage subscribes to an event (exposed from App).
Setting up some Debug.WriteLine along the code I discovered that DevicesPage is still active when navigate back to MainPage (pressing the back arrow or with Navigation.PopAsync()).
Also when I navigate to DevicesPage again the code is executed twice (Degug.WriteLine string in the Output window appear twice) and 3,4,5 etc. times if I keep going back and forward. It seems like a new page gets created every time and the previous still run in background.
I understand that events should be unsubscribed (in that case where should be done). Also it baffles me that the code still seems to be running in the page navigated back. How to remove the page?
DevicesPage is still active when navigate back to MainPage
Just because you navigate away from a page doesn't mean you're done with it. You may want to re-use it later. You can explicitly clean up it's resources if you need to (for instance, unsubscribe your event handlers in OnDisappearing) but this doesn't happen automatically
It seems like a new page gets created every time
it does, because you are explicitly creating a new instance of DevicesPage each time
var p = new DevicesPage(NameofDevice);
Navigation.PushAsync(p);
there is nothing preventing you from keeping a reference to a DevicesPage instance and re-using it instead of always creating a new one

Where should I put navigation code?

I want to skip the login page if there is a token in local storage, but I don't want to move the logic to App, because I want LoginPage to remain my base page.
Currently, I have this code and it works.
public LoginPage()
{
InitializeComponent();
}
protected override void OnAppearing()
{
var localStorage = new LocalStorage();
if (!string.IsNullOrEmpty(localStorage.Get("key")))
{
Navigation.PushAsync(new MainTabbedPage(true));
}
base.OnAppearing();
// some unrelated code...
}
The problem with it is that sometimes (quite often), the login page is visible for a fraction of a second, until it navigates to the MainTabbedPage. Can I put the navigation code from OnAppearing to page constructor? If yes, should I put it before or after InitializeComponent();? Note, that some time in the application, I might call PopToRootAsync() in order to return to the login page, which this time, I might want to display.
Also, please tell me if something is wrong with this approach.
Thanks in advance.
I would highly recommend creating a splash screen. That way you can have a minimum time before the next screen shows and perform tasks. While the splash screen is visible, check if the user token is valid and then proceed to displaying the login screen or whatever screen you want to display.
Please tell me if you need further help.

Navigating back and forth not working

hi i created an app which contains three pages,
if go from MainPage to Page1 and reversely 3 to 4 times it ts working fine, but when i Navigate from Mainpage to Page 2 it is working but when i navigate back from Page 2 to Main Page it is opening MainPage after 1 second it is going back to Page2
can you please tell me the solution for this
Okay i am going to give this a wild guess seeing that you have not given code ,
on each page there is a override method you can use, onNavigatedTo.
what i will do is put an OnNavigatedTo event on each page and put a break point in that event and step to see what each individual page does, here is a quick example where i use onnavigated to test if the navigation to this page was a 'back' navigation!
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
//Check if navigation was back!
// you can add the breakpoint here if you want to.
if (e.NavigationMode == NavigationMode.Back)
{
messagebox.show("Nav is back!");
}
now you can easily see what each individual page does when navigated to :) hope this helps a bit.

Handling Tombstoning and Back key properly for performance reasons?

Is there a best practice for handling tombstoning and back key properly?
As it is stated in the MSDN docu you should save transient data in the OnNavigatedFrom method. Ok, so the code for saving states when tombstoning is clear.
But now if you press the back key the OnNavigatedFrom method is also called and if you don't add extra checks, you will first save states into the dictionary and shortly after that the page will be destroyed. And so will the PhoneApplicationPage.State dictionary. So the saving code is completely wasted CPU, disk and battery time.
This is what I've done to prevent it:
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
// when navigating back
if (e.NavigationMode == System.Windows.Navigation.NavigationMode.Back)
{
backKeyPressed = true;
}
}
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
if (backKeyPressed)
{
// Don't save states on back key!
backKeyPressed = false; // set it anyway
return;
}
// Tombstoning
// save objects
this.SaveState("text", someText);
...
}
As a reminder: OnNavigatingFrom will only be called when navigating away/back from the page but not when app gets tombstoned.
Side note: Shown code covers only pages that can only navigate back. Thats why I added backKeypressed to OnNavigatingFrom. You need extra checks if the page can navigate to another page.
Is there a better way to do this for every page you create?
Now do I really have to add the backKeyPressed variable and check on every page I create?
Shouldn't the framework provide something for us developer so we don't have to worry much about this?
What are your thoughts about this?
EDIT:
Updated question the make it clearer.
your approach of checking the direcetion of navigation in OnNavigatingFrom is indeed the recommended practice in order to avoid the unneccessary performance hit of saving state just before the page gets removed from the backstack.
There is one clarification I want to add to your sample code: You should check the 'NavigationMode' property in the 'NavigationCancelEventArgs' to determine whether it's a forward or backward navigation.
Then only save the state in OnNavigatedFrom if it was a forward navigation, as your sample shows. This will help improve your performance when the user navigates backwards.
Everything you ever needed to know about tombstoning is covered in Jeff Prorise's 4-part Real-World Tombstoning in Silverlight for Windows Phone 7 blog post series. You may want to pay particular attention to part 2 where Jeff talks about clearing up state when the application quits.

Remove a page from Navigation Stack

I have this application schema :
[List Page] -> [Detail Page] -> [ShareOnFacebook Page]
^__________________|
The user select an Item in the [List Page]
The user may or may not click a Share button if he or she does, the application navigates to a [ShareOneFacebook page] which displays a Facebook Login Form, posts a message and navigates back
The user navigates back.
If the user shared on facebook, it will "repost" the message, because the application store the session so it will navigate back to ShareOnFacebook, and then back to my Detail page.
If the user didn't share, he goes back to the List Page.
How can I "ommit" the ShareOnFacebook page in my navigation stack ?
Try this: Call NavigationService.RemoveBackEntry(); in the OnNavigatedTo method. This will remove the previous page from the stack. In my opinion the trick with Navigation.GoBack(); is not satisfying because it shows the page to remove for a short time.
Note: Works only with Windows Phone OS 7.1 (Mango) SDK
I have a similar situation in my app, i solve it with a very simple solution.
If you want to "skip" a page in your backstack, place some logic in the NavigatedTo() function of that page.
For example: you can have a bool that you set to true when you post to facebook, and then place the following code in the NavigatedTo() function of the ShareOnFacebook page.
Here is pseudo code:
if (alreadyPosted)
Navigation.GoBack();
The GoBack() function will skip this page and return to the previous one, the user will never see the page.
Have a look at simple library i wrote for such purposes:
http://navcoerce.codeplex.com/
var fluent = new FluentNavigation(RootFrame);
fluent.WhenNavigatedTo<MainPage>()
.ThenTo<LoginPage>()
.ThenToAnyPage()
.RemoveEntriesFromBackStack(1);
fluent.WhenNavigatedTo<MainPage>()
.ThenTo<LoginPage>()
.ThenTo<RegisterPage>()
.ThenTo<PaymentPage>()
.RemoveEntriesFromBackStackTill<MainPage>();
fluent.WhenNavigatedTo<MainPage>()
.ThenTo<SecondPage>()
.ThenTo<RegisterPage>()
.ThenOptionallyTo<ForgotPasswordPage>()
.ThenToAnyPage()
.RemoveEntriesFromBackStackTill<MainPage>();
fluent.WhenNavigatingTo<PaymentPage>()
.RedirectTo<LoginPage>();
fluent.WhenNavigatingTo<PaymentPage>()
.If(() => false)
.RedirectWithReturnUri<LoginPage>("ReturnUri");
Have a look at the new Nonlinear Navigation Service recipe
Download it from http://create.msdn.com/en-us/education/catalog/article/nln-serv-wp7
I use the removeBackEntry method on the NavigationService Class. I also use this as a way to setup my own splash screens
private void BWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// switch screen
NavigationService.Navigated += new NavigatedEventHandler(NavigationServiceNavigated);
NavigationService.Navigate(new Uri("/Pages/main.xaml", UriKind.Relative));
}
void NavigationServiceNavigated(object sender, NavigationEventArgs e)
{
NavigationService.RemoveBackEntry();
}
I posted an example for the same issue here.
The Nonlinear Navigation Service Matt linked to essentially does the same thing but would probably be better than my simple example.

Resources