How to Navigateback from Xamarin.Forms Prism Popup - xamarin.forms

Xamarin.forms using Prism Navigation back is not working in below scenario :
App.xaml.cs in OnInitialized NavigationService.NavigateAsync(nameof(LoginView));
In LoginViewModel once login I am navigating to MainPage await _navigationService.NavigateAsync(new Uri("MainPage", UriKind.Relative),useModalNavigation:true, animated: false);
MainPaga has a Button once I click in Button it will Popup setting Page navigation Popup like : await _navigationService.NavigateAsync(new Uri("SettingView", UriKind.Relative), useModalNavigation: true, animated: false);
SettingView(Popup) has a Button(LogOut) once I click on Button(LogOut) it has to go back in LoginView here is the code navigating back.
await _navigationService.ClearPopupStackAsync(animated: false);
await _navigationService.GoBackAsync(useModalNavigation: true, animated: false);
first I am Clearing Popup then navigating back, but it wont navigate back to LoginView?

If you are using PRISM and want to 'clear' the current stack.
You better use the explicit uri navigation.
Meaning the code behind the logout button should look like this
await _navigationService.NavigateAsync("/NavigationPage/LoginView");
By adding the / at the beginning of the URI, the current stack will be cleared.

You should just use absolute uri to set Loginpage as Mainpage after user confirm to logout like this
await NavigationService.NavigateAsync(new System.Uri("/LoginPage",System.UriKind.Absolute));

Related

Xamarin Pillar navigation

What is the correct way to handle model navigation?
The first case below works as expected but I can then go back to the login page which I don't want. The second case I can see in the debugger that that page is loaded but never shown. Basically the model page stays on top. I am thinking I need to either close the model page before changing pages or I need to handle this differently. I don't won't to pop to root because the root is no longer home but main.
What I really won't to do is change the root, how?
[Edit] This seems to help but there is still a flicker when I unload the modal page.
await _navigator.PushAsync(vm => { vm.NoHistory = true; });
Case 1:
return viewFactory.Resolve<HomeVM>(); - from APP.cs
await _navigator.PushAsync<LoginVM>();
await _navigator.PushAsync<MainVM>();
Case 2:
return viewFactory.Resolve<HomeVM>(); - from APP.cs
await _navigator.PushModalAsync<LoginVM>();
await _navigator.PushAsync<MainVM>(); - Never works.
One way is to reset MainPage completely with the new page when login in successfully.
if (string.IsNullOrEmpty(authLoginToken))
MainPage = new LoginPage();
else
MainPage = new RootPage();
More detailed info, you can take a look the following thread:
https://github.com/asthanarht/CPXamarin/blob/master/CPMobile/CPMobile/App.cs
https://forums.xamarin.com/discussion/48634/from-login-page-to-main-page

How do I close an MvvmCross MasterDetail page?

I would like my app to show a Login page, then a MasterDetail page with a 'hamburger' menu. On the hamburger menu I want a Log Out entry that closes the Master Detail and shows the Login page again. I have all but the log out part working.
I have copied code from the MvvmCross Playgrounds sample, specifically the MixedNavFirstPage (which fakes a login procedure), MixedNavMasterDetailPage (the 'hamburger menu'), and MixedNavMasterRootContentPage.
If I try to close the MixedNavMasterDetailPage with await _navigationService.Close(this) then I get a null reference exception in MvxFormsPagePresenter.CloseMasterDetailPage()
This question How to Exit (or Navigate out of )a MasterDetail page to a simple ContentPage in Xamarin. Forms? covers what I want to do in straight Xamarin.Forms, I'm just not sure how to do the equivalent in MvvmCross.
In your LoginPage add the MvxContentPagePresentation attribute NoHistory = true
Then simply navigate to the login page, and when the user has logged in, navigate to your MasterDetail page also with NoHistory = true.
When the user logs out again, simply navigate to your LoginPage, and as the NoHistory = true the MasterDetail will be removed completely.
[MvxContentPagePresentation(WrapInNavigationPage = false, NoHistory = true)]
public partial class LoginPage : MvxContentPage<LoginViewModel>
{
public LoginPage()
{
InitializeComponent();
}
}

Xamarin.Forms, using the Prism.Forms NavigationService

I am trying to implement a login scenario with Xamarin Forms and Prism.
My application root page is a MasterDetail page (HomeMasterDetailPage); this being used to provide the side menu.
What I am trying to do is to have the HomeMasterDetailPage page shown with Content set to an instance of LoginPage. When the user logs in, the Content should change to an instance of HomeDetailContentPage. It should not be possible to return to the LoginPage using the back button.
I am using the NavigationService from Prism Forms.
My start up is like this...
public partial class App : PrismApplication {
public App(IPlatformInitializer initializer = null)
: base(initializer) {
}
protected override void OnInitialized() {
InitializeComponent();
Uri uri = new Uri($"/{nameof(NavigationPage)}/{nameof(HomeMasterDetailPage)}/{nameof(HomeDetailContentPage)}", UriKind.Absolute);
var settings = Container.Resolve<SettingsService>();
if (!settings.DeviceUserID.HasValue)
uri = new Uri($"/{nameof(NavigationPage)}/{nameof(HomeMasterDetailPage)}/{nameof(LoginPage)}", UriKind.Absolute);
NavigationService.NavigateAsync(uri);
}
protected override void RegisterTypes() {
Container.RegisterTypeForNavigation<NavigationPage>();
Container.RegisterTypeForNavigation<LoginPage, LoginPageViewModel>();
Container.RegisterTypeForNavigation<HomeMasterDetailPage, HomePageViewModel>();
Container.RegisterTypeForNavigation<HomeMasterContentPage>();
Container.RegisterTypeForNavigation<HomeDetailContentPage>();
}
}
This correctly displays the LoginPage within the HomeMasterDetailPage if the user is not already logged on, and the HomeDetailContentPage within the same HomeMasterDetailPage if the user is logged on.
The problem comes when actually logging on; the following is the code within the view model for the LoginPage...
protected async Task ExecuteLoginCommand() {
Uri uri = new Uri($"/{nameof(NavigationPage)}/{nameof(HomeMasterDetailPage)}/{nameof(HomeDetailContentPage)}", UriKind.Absolute);
await this.navigationService.NavigateAsync(uri);
}
It is my understanding that by using an absolute Uri this should reset the navigation so that the new page arrangement (/NavigationPage/HomeMasterDetailPage/HomeDetailContentPage) is at the top and bottom of the stack, allowing me to then move forward from there. Instead, I am getting an unhandled exception (on Android 7.0).
What am I doing wrong?
Note: All of the examples that I see have the MasterDetailPage at the root with Content being set to NavigationPage/ContentPage; when I try this I do not get exceptions, however the side menu operates differently within the MasterDetailPage - when you tap on the "hamburger" the side menu slides in over everything (including the action/title bar) and the only way to clear it is to tap outside of the side menu that slides in whereas when I show the MasterDetailPage within a NavigationPage the side menu slides in below the action/title bar and the hamburger changes to an arrow that you can click to hide the side menu again.
I can't say I've tested this exact scenario. However, if your LoginPage is the Detail of a MasterDetailPage, you may not want to perform the navigation from the LoginPage. You could, instead create a SuccessfulLoginEvent, which you would then publish from the LoginPage using the IEventAggregator, and you would subscribe to on your MasterDetailPage's ViewModel. You could then perform the navigation as _navigationService.NavigateAsync("NavigationPage/ViewA") and it should reset the Detail such that the back button doesn't bring you to the LoginPage.
Alternatively, you can simply perform an absolute Navigation which has the effect of:
Application.Current.MainPage = new MyPage().
To do to this, you could do the navigation from anywhere as:
_navigationService.NavigateAsync("/MyMasterDetailPage/NavigationPage/ViewA")

How to disable left menu in master detail page in xamarin forms?

I have masterdetail page and there is left menu in it. Its working fine during user is on masterdetail page. But When user move from master detail page to simple content page(that is not part of master detail page), on this content page if he swipe from left to right left menu opens.
How I can disable the left menu on this content page? and why left menu is showing on simple content page while it is not part of the master detail page?
If you're still looking for a solution, you can do it like so:
IsGestureEnabled = false;
You can continue to use
await Navigation.PushAsync(new PageWhichWontOpenTheMenu());
To use it, simply get the RootPage (the MasterDetailPage) on the OnAppearing method like so:
protected override void OnAppearing(){
base.OnAppearing();
(Application.Current.MainPage as RootPage).IsGestureEnabled = false;
}
Tell me if it works for you, cheers!
You can only disable the gesture from master details page.
It can be solve by notifying that the current page is not master page:
1)When we are setting the Master details page by
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsGestureEnabled = true;// always set it true when setting a page to master page
2)Use MessagingCenter from MasterDetails Page for notifying that the current page is not a master page:(inside the master page constructor)
MessagingCenter.Subscribe<string>(this, "DisableGesture", (sender) =>
{
if(sender == "0")
{
IsGestureEnabled = false;
}
else
{
IsGestureEnabled = true;
}
});
3)when you navigate from a nornal content page,and you dont want to open the master menu from here then notify the master page IsGestureEnabled = false;
//content page OnAppearing method
protected override void OnAppearing()
{
MessagingCenter.Send<string>("0", "DisableGesture");
}
do this for all your content page,where you dont want to open master menu.
****and remember that which pages you are setting as master page,for those pages onappearing method send messaging center with value "1"
protected override void OnAppearing()
{
MessagingCenter.Send<string>("1", "DisableGesture");
}
Thanks
Better yet what you can do in your OnMenuItemSelected event for your SideMenu list is check for the type that you want to Disable the SideMenu for and then set IsGestureEnabled to false when navigating to that page:
private void OnMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = (SideMenuItem)e.SelectedItem;
var page = item.TargetType;
if (page == typeof(PageToDisableMenu))
IsGestureEnabled = false;
Detail = new NavigationPage((Page)Activator.CreateInstance(page));
IsPresented = false;
}
I know this answer is late but I hope it helps someone in the future :).
You probably use Detail.Navigation.PushAsync(...) instead of that use Navigation.PushAsync(...)
To really disable, I found one way, use Navigation.PushModalAsync(...). But this way, you don't have the navigation bar at the top anymore. You can build one yourself though.
What worked for was to disable the whole MasterDetailPage with the IsEnabled property.
In may case executing a process from an option menu (not navigation or change the Detail page) and I needed to block any interaction of the user with the page.
Hope this helps.
Regards

Is there a way to disable the background on the DisplayActionSheet using Xamarin Forms?

Issue:
I'm dealing with an issue on how to disable the background on a DisplayActionSheet or DisplayAlert in Xamarin Forms, so the only way the user can "get out" of the popup windows is via the options that the window has prompted.
Here is the screenshot of the problem:
http://postimg.org/image/s16cp66wf/
Do you know if there's a simple way to do this? I've been looking but I couldn't found....
I tried:
Using the methods that came with the control but nothing else came up. What I'm doing right now is to call it till I have an answer.
Code:
From my code behind I call the event
async void OnNextClicked(object sender, EventArgs args)
{
await userValidations.RMLocationServiceWindow();
}
And then I call the popup window
public async Task RMLocationServiceWindow ()
{
string rta = null;
while (rta == null)
{
rta = await App.Current.MainPage.DisplayActionSheet("Do you accept to use the service?", "Cancel", "Continue");
}
}
I couldn't find any that keep the focus on the windows.
Unfortunately this could not be done in displayactionsheet, for you to be able to achieve this, you must create a Modal Page with list where you could be able to disable back button until there is a selection on the list. hope it helps
I think I got your problem. If your problem is about when user not click 'Cancel' or 'Continue' and he click empty space, you wont get value for rta. Think about if user click white space it mean is canceling. This way may help you.
while (rta == null)
{
rta = await App.Current.MainPage.DisplayActionSheet("Do you accept to use the service?", "Cancel", "Continue");
if (rta==null)
rta=="Cancel";
}

Resources