I have this code below to create an action bar with an integrated side bar using <Shell> so the user can navigate easily by swiping right. Being new to C#, I understand that the first ShellContent is gonna be the page to be loaded and previewed by the <Shell> when the app opens which is ContentTemplate="{DataTemplate local:LoanHistory}"
I also understand when you click on the FlyoutItems you aren't gonna add stack to the navigation but the <Shell> is changing the contents each time you click on it. This code below is in a file called MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LoanApp2.Views"
mc:Ignorable="d"
x:Class="LoanApp2.MainPage" BackgroundColor="#62bef0" Title="Dylan">
<FlyoutItem Title="MyTabApp" Shell.TabBarIsVisible="False" FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="Loan History" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanHistory}"/>
<ShellContent Title="Apply for Loan" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanApplication}"/>
<ShellContent Title="Logout" IsTabStop="False" ContentTemplate="{DataTemplate local:LoanHistory}"/>
</FlyoutItem>
</Shell>
So, via the side bar (shell) - I click on Apply for Loan which takes me to LoanApplication.xaml. By this time, no stack is added to the navigation. In the LoanApplication.xaml, I'm using PushAsync binded to a button to take me to a page called AmountLoanable.xaml. This gets added to the stack and the back button on the action bar is now available.
After I am done with the stuff on AmountLoanable.xaml, I use PopToRootAsync to remove the navigation stack except for the root page (which is the <Shell>, MainPage.xaml). However, it takes me back to the "Apply for Loan" which was selected prior, what I want to happen is for it to load a fresh new <Shell>, MainPage.xaml page. In that way, the first page (Loan History) will be the one selected instead of the last page accessed via <Shell>
try to reset your Application.Current.MainPage to your default Shell ex: Application.Current.MainPage = new AppShell();
Related
trying to make a flyout menu in .net maui, from what i found out i have to use App.xaml for it, it does not seem to be working, here is the code in App.xaml
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:NSM_Maui"
x:Class="NSM_Maui.App">
<Application.MainPage>
<Shell FlyoutBehavior="Flyout" FlyoutHeaderBehavior="Fixed" FlyoutVerticalScrollMode="Auto">
<FlyoutItem Title="Home" >
<ShellContent ContentTemplate="{DataTemplate local:HomePage}"/>
</FlyoutItem>
</Shell>
</Application.MainPage>
it work fine up to the but the does not seem to be working, the Datatemplate string is a ContentPage xaml file that i made its called "HomePage" i was also following this videoenter image description here https://youtu.be/KUzpFrReJNQ
i fixed it, iam not really sure what i changed but i had to make a new project and in the AppShell.xaml there is the tag and you have to add Shell.FlyoutBehavior="Flyout" and also add the <ShellContent> tag <ShellContent>
I am new to xamarin forms and shell and I am currently trying to design the hierarchial structure of an app using Shell (Xamarin.Forms Shell). I want to design my app so that once the user logs in, he will be taken to a page (let's call it home page one) that can be chosen from the flyout menu and has it's own unique tabs at the bottom. I also want there to be another page visible in the flyout menu (let's call it home page two) so that if the user clicks on home page two, it is taken to home page two, which has it's own different tabs at the bottom. The user should see different tabs depending on which home page they chose in the flyout menu.
Here's the idea of the overall layout:
Once user starts up application, they are taken to a start page (StartPage)
The start page gives the user the choice to login (LoginPage) or register (RegistrationPage)
Once the user successfully logs in, they are taken to home page one(HomePageOne) which contains 4 tabs at the bottom
If the user opens the flyout menu, it should display an item for HomePageOne and HomePageTwo, as well as a logout menu item.
If the user clicks on home page two (HomePageTwo), they are taken to home page two, which has different tabs from home page one and vice versa
If the user chooses to logout, they are taken back to the start page (StartPage)
I currently have two questions. First, I'm not sure how to define my shell to account for the different home pages having different tabs. Second, when the user chooses to logout, it is still displaying the flyout menu (hamburger menu) even though that should only be visible while the user is successfully logged in.
Here is my AppShell.xaml:
<ShellItem Route="Start" FlyoutItemIsVisible="False">
<ShellContent Route="StartPage" ContentTemplate="{DataTemplate local:StartPage}" />
</ShellItem>
<ShellItem Route="Login" FlyoutItemIsVisible="False" >
<ShellContent Route="LoginPage" ContentTemplate="{DataTemplate local:LoginPage}" />
</ShellItem>
<ShellItem Route="Registration" FlyoutItemIsVisible="False" >
<ShellContent Route="RegistrationPage" ContentTemplate="{DataTemplate local:RegistrationPage}" />
</ShellItem>
<FlyoutItem Title="Home Page One" Icon="icon_about.png">
<ShellContent Route="HomePageOne" ContentTemplate="{DataTemplate local:HomePageOne}" />
</FlyoutItem>
<FlyoutItem Title="Home Page Two" Icon="icon_feed.png">
<ShellContent Route="HomePageTwo" ContentTemplate="{DataTemplate local:HomePageTwo}" />
</FlyoutItem>
<!-- When the Flyout is visible this will be a menu item you can tie a click behavior to -->
<MenuItem Text="Logout" StyleClass="MenuItemLayoutStyle" Clicked="MenuLogout_Clicked">
</MenuItem>
Here is my AppShell.xaml.cs:
public partial class AppShell : Xamarin.Forms.Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(StartPage), typeof(StartPage));
Routing.RegisterRoute(nameof(RegistrationPage), typeof(RegistrationPage));
Routing.RegisterRoute(nameof(LoginPage), typeof(LoginPage));
}
private async void MenuLogout_Clicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("StartPage");
}
}
I found the answer by watching a couple of videos by James Montemagno on youtube. If you are new to xamarin, I highly recommend these videos!
https://www.youtube.com/watch?v=ylbgWHB_gMI&t=1s - Login flow
https://www.youtube.com/watch?v=8iYpLMKE_ws&t=1067s - Shell Navigation
I'm having a problem with how to implement navigation to pages that are not represented in shell visual hierarchy (defined in my Shell xaml).
From what I read about Shell navigation in the docs, there are two ways I can navigate to such a page:
Using the Navigation property:
Navigation.PushAsync(new TargetPage());
Registering a route and using Shell's URI navigation:
Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
Shell.Current.GoToAsync("targetPageRoute");
Both methods encounter the same problem: Once you use either method to navigate to a page outside the visual hierarchy, normal navigation between Shell's flyoutItems (using the flyout menu) will crash the app with the error:
System.Collections.Generic.KeyNotFoundException: The given key 'MyProject.TargetPage' was not present in the dictionary.
How to reproduce:
Add two items to Shell's visual hierarchy:
<FlyoutItem Title="page 1">
<Tab>
<ShellContent>
<local:Page1 />
</ShellContent>
</Tab>
</FlyoutItem>
<FlyoutItem Title="page 2">
<Tab>
<ShellContent>
<local:Page2 />
</ShellContent>
</Tab>
</FlyoutItem>
Use a button on Page1 to navigate to Page3 (a page not defined above) using either of the two ways to navigate described at the top of this post:
private void Button_Clicked(object sender, EventArgs e) {
Navigation.PushAsync(new Page3());
}
Use the flyout menu to navigate to Page2
Use the flyout menu to navigate to Page1 - the app should now crash.
I have tested this in my main project and in a small test project extensively and cant seem to find a solution. Any help would be greatly appreciated.
Here's the same issue from xamarin forms' github: https://github.com/xamarin/Xamarin.Forms/issues/6738
Also, if you scroll down, you'll see pull request, which actually resolves the problem (already helped our company's application).
You have to implement a custom renderer, which is going to inherit from ShellItemRenderer, and override the existing HandleFragmentUpdate (because of the fact, that it uses private fields from the original ShellItemRendererBase, you'll have to rebase them here too (not override, just copy them from current xamarin android ShellItemRendererBase.cs file)).
BUT, as the official docs suggest, you shall not just assign this renderer to a ShellItem derivative, instead, you'll have to create custom ShellRenderer with overriding it's CreateShellItemRenderer method (so it would create your fixed shell item renderer instead of the default one). You just apply this renderer to a custom shell control in xamarin forms.
Of course, everything you do now is temporary, until xamarin pushes new update with this fix included...
you could try to change the shell.xaml like this:
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<Tab Title="page 1">
<ShellContent >
<local:Page1 />
</ShellContent>
</Tab>
<Tab Title="page 2">
<ShellContent >
<local:Page2 />
</ShellContent>
</Tab>
</FlyoutItem>
Have you tried to add your Route before setting the BindingContext ?
For Example :
public NavigationShell()
{
Routing.RegisterRoute("targetPageRoute", typeof(TargetPage));
BindingContext = this;
}
So I was thinking of displaying a small statusbar during the debugging over my navigation page. Basically something like this:
<?xml version="1.0" encoding="utf-8" ?>
<NavigationPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Drivr.Pages.MainPage">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Text="Status of app" Grid.Row="0" />
<NavigationPage x:Name="MainNavigation" Grid.RowSpan="2" Grid.Row="0"></NavigationPage>
</Grid>
</NavigationPage>
Not exactly that of course, but you have the idea. So when there is like an error or I want to try something I could just display it there instead of outputting it to the console. Is it possible of doing something similar to this?
Yes, but not like this.
The NavigationPage is a construct that allows you to maintain a navigation stack - that is a set of pages where the top page is the currently visible one and clicking "Back" button removes (pops) the top page so the previous one becomes the top one.
You could also pop all the way to the root of the navigation stack so you can go "home". With several NavigationPages where a one is put (pushed) you could create a set of checkpoints so the user can quickly go back to a previous page that may be further than one step back.
In your case you could add to App.cs' constructor:
MainPage = new NavigationPage(new ContentPage{
Content = new Label { Text = "here we are" }
});
This sets up a root NavigationPage, so in your other pages you can do:
async void OnButtonClick(...){
await Navigation.PushAsync(new MyNextPage());
}
Normally the "Back" button will show up by itself, and now you'd have a simple 2-page app.
I have a Xarmarin Forms application using Prism and Unity and am having trouble with navigation to a tabbed page.
I'm using the following versions: Prism.Forms v6.1.0-pre5 Prism.Unity.Forms v6.2.0-pre5 Xamarin.Forms v2.3.0.38-pre2
My tabbed page looks like this
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:local="clr-namespace:ServiceOrdersMobileApps.Views;assembly=ServiceOrdersMobileApps"
x:Class="ServiceOrdersMobileApps.Views.ServiceOrderTabs">
<NavigationPage Title="Summary">
<x:Arguments>
<local:ServiceOrderSummary />
</x:Arguments>
</NavigationPage>
<NavigationPage Title="Complete">
<x:Arguments>
<local:ServiceOrderDetails />
</x:Arguments>
</NavigationPage>
</TabbedPage>
I'm trying to navigate to the tabbed page with the Service Order Detail Page selected but when I navigate according to this blog post. It navigates past the tabbed page to a separate Service Order Detail Page
var p = new NavigationParameters();
p.Add("serviceorder", context);
await _navigationService.NavigateAsync($"{nameof(ServiceOrderTabs)}/{nameof(ServiceOrderDetails)}",p);
You have the page wrapped in a generic NavigationPage that Prism doesn't know about. You need to create a derived NavigationPage and register it for navigation. Then use that to wrap your COntentPages. Then you can try navigating like "ServiceOrdersTabs/MyNavigationPage/ServiceOrdersDetails".
But even this may not work now that I think about it, because you'll have multiple instances of the same NavigationPage and Prism will use the first one it finds and use that.
For a work around, you'll have to create a different NavigationPage for each tab (ServiceOrderSummaryNavPage, ServiceOrdersDetailsNavPage, etc) to ensure that each Tab is unique.
By the way, from where are you navigating?