Where should I put navigation code? - xamarin

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.

Related

Xamarin Shell: Redirect to different page and remove current page from nav stack

I imagine this is pretty straightforward, but I'm struggling to make sense of how to do it via the documentation...
I've got a tab page, that is opened from a flyout item.
The tabs for this page are dynamically loaded from saved data in the code behind, and all works exactly as expected.
However, in the scenario when there is no saved data (and thus, no tabs) I want to redirect the user to a different page, and crucially, not be able to navigate back to this tab page (but allow going back to the page they were initially on BEFORE they navigated to the tabbed page)
I've got a method in initalize for the tabbed page that, if it doesn't have any saved data, attempts to do this. I started with:
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(AddNewDataPage));
which navigated to the add page, but pressing the back button just resulted in the add page being shown again, over and over.
I then tried:
Shell.Current.Navigation.PopToRootAsync();
Shell.Current.GoToAsync(nameof(AddNewDataPage));
which did the same.
So next I went with trying to navigate backwards:
Shell.Current.GoToAsync("../" + nameof(AddNewDataPage));
which showed the right page again, but now the back button doesn't work
Next, I went with trying an absolute route:
Shell.Current.GoToAsync("//HomePage/" + nameof(AddNewDataPage));
which worked... sort of.
The first time the user clicks the flyout for the tabbed page, it all works great. back button takes you to the home page etc... but the second and subsequent times the user clicked the flyout, they navigate to the tabbed page and my LoadData method isn't called.
I assumed this is because the tabbed page is still loaded, so I added:
protected override void OnAppearing()
{
LoadData();
}
Now, when the user clicks the flyout for the second and subsequent times, they navigate to the HomePage page instead of the AddNewDataPage page (an improvement, I guess?)
So, now I'm at a loss.. it seems like this should be really simple, but I can't figure it out.
You can try this.
//route The route hierarchy will be searched for the specified route, upwards from the current position. The matching page will replace the navigation stack.
https://learn.microsoft.com/nl-nl/xamarin/xamarin-forms/app-fundamentals/shell/navigation?WT.mc_id=friends-0000-jamont#relative-routes
await Shell.Current.GoToAsync($"//{nameof(AddNewDataPage)}");
https://www.youtube.com/watch?v=ylbgWHB_gMI&t=703s&ab_channel=JamesMontemagno
An explanation about relative routes.
May I don't understand your problem clearly. But I created a simple with the flyout shell app.
At first, it seems that the construction method of the content page will jut call once which the page shows first time. So I put the following code into it. Such as:
public ItemsPage()
{
InitializeComponent();
BindingContext = _viewModel = new ItemsViewModel();
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(NewItemPage));
}
And then when the app got into the ItemsPage first time, it will get into the NewItemPage. User can add new item here. After that, when I clicked the back button, I will get into the ItemsPage back without it's construction method called. So you can't add the LoadData(); in it.
You can put it into the OnAppearing method. Such as:
protected override void OnAppearing()
{
//LoadData();
if (_viewModel.Items.Count < 8)
{
Shell.Current.Navigation.PopAsync();
Shell.Current.GoToAsync(nameof(NewItemPage));
// then add two item in the NewItemPage
}
else {
base.OnAppearing();
_viewModel.OnAppearing();
}
}
This will get the same effect as above. I also try to move the Shell.Current.Navigation.PopAsync();. The result is same. It will get back to the ItemsPage when you clicked the back button in the NewItemPage after you add two item.
which navigated to the add page, but pressing the back button just resulted in the add page being shown again, over and over.
You may just need a if() to judge the condition the app need to go to the AddNewDataPage with skipping the tab page.

How to save the information on a Page when traveling from one detail page to another

I am working with Xamarin.Forms and I am trying to implement my multipage form in a Master-Detail format. When I click on another page from the Master page menu, I want to make sure that the information on the current detail page gets saved to its respective database table on the mobile device before I travel to the next detail page. Any idea on how to achieve that?
Have you looked at the OnDisappearing() method?
protected override void OnDisappearing()
{
//Your code before you switch to another page
}
Hi #lovetolearn you can achieve this things OnDisappearing() method of each page.
protected override void OnDisappearing()
{
//Your code before you switch to another page
}

How to finish current page in Windows Universal

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.

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.

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