Navigate within modal dialog using shell - shell

I'm using shell to navigate in my Xamarin Forms app. I want my settings to be in a Modal dialog which is navigated to by calling PushModalAsync. In that settings page I want to navigate to other pages, eg password change. But since I'm not using NavigationPage I cannot get it to work.
How do one use Shell with Modal and navigate within that Modal page?
I can get it to work by setting my SettingsPage as a new MainPage. But then I don't get the modal navigation animation.

using NavigationPage will probably solve the problem but then I will
no longer use Shell which I want to use.
I think wrap your Settings page in a NavigationPage would solve your problem. You can still use Shell after using NavigationPage.
For example, you can do some push actions in the SettingPage:
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new BearDetailPage());
}
In the BearDetailPage, if you want to use Shell, you can dismiss the SettingPage by send a message usingMessagingCenter:
private async void Button_Clicked(object sender, EventArgs e)
{
await Navigation.PopToRootAsync(false);
MessagingCenter.Send<BearDetailPage>(this, "BackToShell");
}
And in the SettingPage, subscribe that message:
public SettingPage()
{
InitializeComponent();
MessagingCenter.Subscribe<BearDetailPage>(this, "BackToShell", (sender) =>
{
// Do something whenever the "BackToShell" message is received
this.Navigation.PopModalAsync();
});
}
If you don't want the navigationbar in the SettingPage, you can just hide it.

Related

Detect Back Arrow Press Of The NavigationPage in Xamarin Forms

Is there any way to detect the press of the back button of the Navigation Page in Xamarin forms?
You can override your navigation page "OnBackButtonPressed" method:
protected override bool OnBackButtonPressed()
{
Device.BeginInvokeOnMainThread(async () =>
{
if (await DisplayAlert("Exit?", "Are you sure you want to exit from this page?", "Yes", "No"))
{
base.OnBackButtonPressed();
await App.Navigation.PopAsync();
}
});
return true;
}
If you are using the shell, you can override the Shell's OnNavigating event:
void OnNavigating(object sender, ShellNavigatingEventArgs e)
{
// Cancel back navigation if data is unsaved
if (e.Source == ShellNavigationSource.Pop && !dataSaved)
{
e.Cancel();
}
}
Update:
OnBackButtonPressed event will get fired ONLY on Android when user press the Hardware back button.
Seems like you are more interested to implement when any page get disappeared you want to do something!
In that case:
You have the page's two methods -
protected override void OnAppearing()
{
base.OnAppearing();
Console.WriteLine("Hey, Im coming to your screen");
}
protected override void OnDisappearing()
{
base.OnDisappearing();
Console.WriteLine("Hey, Im going from your screen");
}
You can override those 2 methods on any page to track when they appear and disappear.
Recent updates to Xamarin forms mean you can now do this in an application made with Shell Navigation for navigation back arrow on both platforms.
Use the Shell.SetBackButtonBehavior method, for example running this code in the constructor of your page object will allow the back navigation to take place only when the bound viewmodel is not busy:
Shell.SetBackButtonBehavior(this, new BackButtonBehavior
{
Command = new Command(async() =>
{
if (ViewModel.IsNotBusy)
{
await Shell.Current.Navigation.PopAsync();
}
})
});
In the body of the Command you can do whatever you need to do when you are intercepting the click of the back button.
Note that this will affect only the navigation back button, not the Android hardware back button - that will need handling separately as per the answers above. You could write a shared method called from both the back button pressed override and the command on shell back button behaviour places to share the logic.
You must override native navigationbar button behavior with custom renderer. OnBackButtonPressed triggers only physical device button. You can read good article how to achive this here

Button x:Name="btnBack" not navigating to previous page

I am developing Xamarin Forms application for IOS and Android.I have the list of 3 xamarin form pages say X.xaml, Y.xaml, Z.xaml. Page X.xaml, Y.xaml is having 1 and click on that button it opens the next-next Xamarin form. And last on Z.xaml having 2 buttons btnBack & btnConfirm
<Button x:Name="btnBack"></Button>
<Button x:Name="btnConfirm"></Button>
when I click on that back button I want to navigate it to my previous page, but I don't want it like Navigation Back Button or Hardware Back Button click.
for this I have tried this code this will not work.
Z.xaml.cs
public partial class Z : ContentPage
{
public Z()
{
InitializeComponent();
btnBack.Clicked += btnBack_Clicked;
}
private void btnBack_Clicked(object sender, EventArgs e)
{
var existingPages = Navigation.NavigationStack.ToList();
foreach (var page in existingPages)
{
if(page == this)
Navigation.RemovePage(page);
}
}
}
In this code when I click on Back Button it Navigate me to prevoius page ie Y.xaml once I click on button which is on Y.xaml and open the Z.xaml page it shows me blank.
Y.xaml.cs
public partial class Y: ContentPage
{
public Y()
{
InitializeComponent();
btnZ.Clicked += btnZ_Clicked;
}
void btnZ_Clicked(object sender, System.EventArgs e)
{
Navigation.PushAsync(new Z());
}
}
#Kowalski had the right answer however it is incomplete.
You have to await Navigation.PopAsync() otherwise you may mess up the navigation stack. So always await it. Example:
async void btnBack_Clicked(object sender, EventArgs e)
{
await Navigation.PopAsync();
}
Beside that be aware that there are bugs in Xamarin.Forms related to navigation, here is one that might be interesting for you as well:
https://bugzilla.xamarin.com/show_bug.cgi?id=59172
P.S.: Here you can find the official guide on Popping Pages from the Navigation Stack.
you should invoke Navigation.PopAsync() to go back

How to close a content page on button click and remove that from stack in xamarin forms?

want to close a content page on button click and remove it from stack,so how to achieve this.PopAsync is not working for me.
To remove some page of you navigation stack you can use.
this.Navigation.RemovePage (this.Navigation.NavigationStack [your page index]);
but if you just want to go back screen or go to main page of your navigation stack you can use this.
this.Navigation.PopAsync ();
this.Navigation.PopToRootAsync();
you need to call
Application.Current.MainPage.Navigation.PopAsync();
from async void.
for example if you have button click handler just add async keyword before void like this:
private async void Button_Clicked(object sender, EventArgs e)
{
await Application.Current.MainPage.Navigation.PopAsync();
}

How to stop reload page after navigation windows phone?

My mainpage call to Page1. I add a webbrowser control to the Page1. When the webbrowser load data complate, I go the background.Then, i back my Page1, webbrowser reload data. How to stop reload it?
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mlink = NavigationContext.QueryString["link"];
web.Navigate(new Uri(_mlink, UriKind.Absolute));
}
You can use the NavigationEventArgs.NavigationMode property to determine which direction the navigation is coming from.
The available options can be found here (MSDN), but listed out, they are:
New
Back
Forward
Refresh
So my tip would be to determine which value of this you want to navigate the web browser control on (I would guess New).
NavigationEventArgs.NavigationMode works only in windows phone 8. So edit the code like this.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
_mlink = NavigationContext.QueryString["link"];
if(web.Source.AbsolutePath!=_mlink)
web.Navigate(new Uri(_mlink, UriKind.Absolute));
}

WebBrowser control: show to user when it's navigating

I'm developing a Windows Phone application.
I'm using WebBrowser control and I want to show to users when is loading a page. I've used events:
private void Browser_Navigating(object sender, Microsoft.Phone.Controls.NavigatingEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Visible;
}
private void Browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Collapsed;
}
But it doesn't work.
Any advice?
I think your problem is in the navigated event - this
From msdn
Occurs when the WebBrowser control has navigated to a new document and has begun loading it.
This obviously could be long before the document is actually rendered.
I'm not sure there's any event to use to determine when the page is fully loaded and is rendered.
In iron7, I detect when the editor is loaded by using a timer - that timer keeps trying to call javascript methods in the script - I know these are only available after the document javascript ready occurs.
Try using the LoadCompleted event:
private void Browser_LoadCompleted(object sender, NavigationEventArgs e)
{
LoadingText.Visibility = System.Windows.Visibility.Collapsed;
}
This ensures that once everything is rendered the loading bar will disappear.
See the msdn page: http://msdn.microsoft.com/en-us/library/microsoft.phone.controls.webbrowser.loadcompleted(v=VS.92).aspx
(I think Stuart was looking at the Windows Forms implementation of WebBrowser rather than the Phone Control)

Resources