Xamarin: Pop modal form after another modal form was pushed - xamarin

I have a problem to remove a modal from the stack after another modal was pushed.
I have a content page where the user can select a product. Clicking on the ListView opens a modal form with product details. On this modal form is a button to add the product to a wishlist which opens a new modal form for the wishlist details. I want to close the first modal form after the new modal form was launched.
Here is the sample code:
private async void Btn_addToWishlist_Clicked(object sender, EventArgs e)
{
try
{
var item = sender as Button;
if(Controllers.CurrentProductModel == "Products")
{
AllProducts product = item.BindingContext as AllProducts;
var nextpage = new WishlistSelectorPopupPage
{
BindingContext = product
};
await Navigation.PushModalAsync(nextpage);
}
else if(Controllers.CurrentProductModel == "AllProducts")
{
AllProducts product = item.BindingContext as AllProducts;
var nextpage = new WishlistSelectorPopupPage
{
BindingContext = product
};
await Navigation.PushModalAsync(nextpage);
}
Navigation.RemovePage(this);
}
The last line "Navigation.RemovePage(this)" brings an error because it is a modal page.
How can I adress to remove or pop a specific modal page?

would this help?
var previousPage = Navigation.NavigationStack.LastOrDefault();
await Navigation.PushAsync(new CustomPage());
Navigation.RemovePage(previousPage);
or
var _navigation = Application.Current.MainPage.Navigation;
var lastPage = _navigation.NavigationStack.LastOrDefault();
_navigation.RemovePage(lastPage);

Related

Unable to Navigate pages while keeping the tab bar accessible in xamarin forms

So I have a tab bar and some pages attached to it, and what I'm trying to do is navigate to a different page(not a tab bar page) by clicking a button which is present in one of these tab bar pages, on doing so that page is replacing the tab bar, how would I be able to navigate inside the tab bar itself, I checked a couple of threads and doing a PushAsync should do the trick but its not working
This is a snippet of my NavigateAsync Method
public async Task NavigateAsync(string pageKey, object[] parameter, bool animated = true)
{
var page = GetPage(pageKey, parameter);
await CurrentNavigationPage.Navigation.PushAsync(page, animated);
}
private readonly Stack<NavigationPage> _navigationPageStack = new Stack<NavigationPage>();
private NavigationPage CurrentNavigationPage => _navigationPageStack.Peek();
We have a CurrentPage property in TabbedPage. You will need this CurrentPage.Navigation object to push the page inside tab bar itself.
So it turns out in my navigation service, i was using the tabbedpage as a navigationpage to navigate to other pages, but if you get the current page (which should be encapsulated in a navigation while adding them as children to your tabbedpage), then using that if you navigate it creates a new page inside the current page instead of the whole tabbedpage
Here's my syntax for storing the currentPage as my navigation element to navigate
public Page SetRootPage(string rootPageKey = null, Page pageName = null)
{
NavigationPage tempPage = null;
if (rootPageKey != null)
{
var rootPage = GetPage(rootPageKey);
if (rootPage is TabbedPage tabbedRootPage)
{
tempPage = tabbedRootPage.CurrentPage as NavigationPage;
}
if (tempPage == null)
{
CurrentNavigationPage = rootPage is NavigationPage ? (NavigationPage)rootPage : new NavigationPage(rootPage);
}
else
{
CurrentNavigationPage = tempPage;
}
return CurrentNavigationPage;
// as NavigationPage;
//_navigationPageStack.Clear();
//var mainPage = new NavigationPage(rootPage);
// _navigationPageStack.Push(mainPage);
}
else
{
if (pageName is TabbedPage tabbedPage)
{
CurrentNavigationPage = tabbedPage.CurrentPage as NavigationPage;
}
else
{
CurrentNavigationPage = pageName as NavigationPage;
}
return CurrentNavigationPage;
}
}

Xamarin - How to know what has been clicked in collection view?

I have a CollectionView with an image and a button in it. I use following code to see if somebody pressed anywhere within the cell:
private void CollectionView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (((CollectionView)sender).SelectedItem != null)
{
var item = (picdata)e.CurrentSelection.FirstOrDefault();
((CollectionView)sender).SelectedItem = null;
if (allowfullscreen == "1" || allowfullscreen == "true")
{
Navigation.PushAsync(new Picture());
}
}
}
But how can I know if he clicked the button inside the cell? I was trying to do it via the Click event, but then I do not know which one of all the buttons has been clicked.
you can get the item from the BindingContext of the sender
var item = (picdata)(Button)sender.BindingContext;

how to prevent back button to login page after user logs in ( Xamarin Forms)

i have a log in page where user enters username and password and then the user is redirected to his account page, but when i press the back button it takes me back to the log in page. How do i prevent that from happening.
Code Snippet:
public Login ()
{
if (App.IsUserLoggedIn == false)
{
InitializeComponent();
}
else
{
Navigation.PushAsync(new NavigationPage(new LoginIndexPage()));
}
}
private async void LoginButton_Clicked(object sender, EventArgs e)
{
var user = new Xcore.Users.csUser
{
RefNo = referansnoEntry.Text,
Username = usernameEntry.Text,
Password = passwordEntry.Text
};
var isValid = IsCorrectLogin(user);
if (isValid)
{
App.IsUserLoggedIn = true;
await Navigation.PushAsync(new NavigationPage(new LoginIndexPage()));
}
else
{
showError.Text = "*Hatalı giriş";
passwordEntry.Text = string.Empty;
usernameEntry.Text = string.Empty;
referansnoEntry.Text = string.Empty;
}
}
private bool IsCorrectLogin(Xcore.Users.csUser user)
{
return user.RefNo == Xcore.Users.RegInfo.RefNo
&& user.Username == Xcore.Users.RegInfo.Username
&& user.Password == Xcore.Users.RegInfo.Password;
}
public LoginIndexPage()
{
if (App.IsUserLoggedIn == true)
{
InitializeComponent();
}
else
{
Navigation.PushAsync(new NavigationPage(new Login()));
}
}
protected override void OnAppearing()
{
base.OnAppearing();
showuserName.Text = Xcore.Users.RegInfo.Username;
}
When i login, its going on LoginIndexPage.
Similar to what App Pack mentioned, you should not have LoginPage in the navigation stack. Instead of trying to remove it, just set the next page to the root page.
Instead of pushing the next page onto the stack, set it :
Application.Current.MainPage = <your next page>
Also, I wouldn't navigate to a page in the constructor of a page. That's not really a good practice.
Usually in this situation I would remove the login page from the Navigation Stack.
I believe there is a method on Navigation such as Navigation.RemovePage(Page page) as you are navigating away from the login page. That way your back-stack and functionality stays in place but will not go back to the login page as it has been removed from the stack.
What you must remember however, is that if the login was the root page, there does need to still be a page in the stack when you call pop().
try use this code in your LoginIndexPage.
protected override bool OnBackButtonPressed()
{
return true; // true prevent navigation back and false to allow
}

Navigating from TabbedPage to ContentPage

I have a TabbedPage with three tabs which is my main page. In one of the tabs I have a ListView and on clicking on the Item in ListView I want to navigate to a new Page.
I can navigate to the new page but the page is displayed within the tab. I do not want the page to be within the tab and should take be opened a new page taking the whole screen.
This is my listView itemSelected method within one of the tabs.
How can I make the DocketDetail page take the entire screen.
I have tried making it the 'MainPage' which
App.Current.MainPage = new NavigationPage(new DocketDetail());
But doing this I could not go back to the TabbedPage.
Please suggest
lvLiveDockets.ItemSelected += (object sender, SelectedItemChangedEventArgs e) =>
{
if (e.SelectedItem == null)
{
DisplayAlert("Item DeSelected", e.SelectedItem.ToString(), "Ok");
return; //ItemSelected is called on deselection, which results in SelectedItem being set to null
}
else
{
DisplayAlert("Item Selected", e.SelectedItem.ToString(), "Ok");
this.Navigation.PushAsync(new DocketDetail());
}
//((ListView)sender).SelectedItem = null; //uncomment line if you want to disable the visual selection state.
};
My App.Xaml.cs
MainPage = new TabbedPage
{
Children =
{
new NavigationPage(new PendingDockets())
{
Title = "Pending Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
new NavigationPage(new LiveDockets())
{
Title = "Live Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
new NavigationPage(new ArchiveDockets())
{
Title = "Archive Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
}
};`
Your App.cs could be changed to this:
MainPage = new NavigationPage(new TabbedPage()
{
Children =
{
new PendingDockets()
{
Title = "Pending Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
new LiveDockets()
{
Title = "Live Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
new ArchiveDockets()
{
Title = "Archive Dockets",
Icon = Device.OnPlatform<string>("tab_about.png",null,null)
},
}
});
You have to put the TabbedPage inside a Navigation Stack (I think as Root page)
Application.Current.MainPage = new NavigationPage(new Tabpage());
when you select yout item in listview, you should push a new page
Navigation.PushAsync(new DocketDetail());
I hope to have understand your problem
lvLiveDockets.ItemSelected += (object sender, SelectedItemChangedEventArgs e) =>
{
if (e.SelectedItem == null)
{
DisplayAlert("Item DeSelected", e.SelectedItem.ToString(), "Ok");
return; //ItemSelected is called on deselection, which results in SelectedItem being set to null
}
else
{
DisplayAlert("Item Selected", e.SelectedItem.ToString(), "Ok");
Application.Current.MainPage = new DocketDetail();
}
//((ListView)sender).SelectedItem = null; //uncomment line if you want to disable the visual selection state.
};

Navigation Master-Detail using MvvmCross Forms and Xamarin Forms

I am having some problem in the nagivation between the Master ans Detail Page using MvvmCross Forms, the page opens up in blank.
class MasterPage : MasterDetailPage
{
public MasterPage()
{
var masterContentPage = new MasterContentPage();
masterContentPage.ListView.ItemSelected += (sender, e) => NavigateTo(e.SelectedItem as MasterPageItem);
Master = masterContentPage;
Detail = new PaymentMethodsListPage();
}
void NavigateTo(MasterPageItem menu)
{
Page displayPage = (Page)Activator.CreateInstance(menu.TargetType);
Detail = displayPage;
IsPresented = false;
}
}
How can I bind my navigation to the ViewModel?
Thanks.

Resources