Xamarin Shell use Contentview inside ShellContent - xamarin

I have the following code in my AppShell.xaml
<Shell ....
...
<TabBar Shell.TabBarUnselectedColor="Green" Shell.BackgroundColor="Gray" Shell.NavBarHasShadow="True" Shell.NavBarIsVisible="False">
<ShellContent Title="WebView" Icon="icon_about.png" Route="LoginView" >
<local:LoginPage/>
</ShellContent>
<ShellContent Title="Listing" Icon="icon_about.png" Route="ListingView" ContentTemplate="{DataTemplate local:ListingView}" />
...
Where LoginPage is / has to be a ContentView, because I need to display other Views inside of it.
But I can't figure out how to use a ContentView as ShellContent because every time i get a specified cast is not valid-exception. Is there any other way to use a ContentView inside ShellContent?
Thanks in advance

A ShellContent object represents the ContentPage object for each FlyoutItem or Tab.
We can't set a ContentView inside ShellContent .
The only way is to place the LoginView into a ContentPage , and then use in ShellContent.

Related

Dynamic Tabs in Maui Shell

I'm trying to create an App where Tabs can be dynamically added and removed during runtime. I have a Tabbar in my AppShell.xaml, as seen in the following code sample:
<Shell
x:Class="foo.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:foo"
xmlns:views="clr-namespace:foo.Views"
Shell.FlyoutBehavior="Disabled"
Shell.BackgroundColor="{DynamicResource ShellBackGroundColor}">
<TabBar x:Name="MainTabBar">
<ShellContent Title="Home"
Icon="alert_icon_2_neg.png"
ContentTemplate="{DataTemplate views:StartPage}">
</ShellContent>
</TabBar>
</Shell>
The code I use to update the Tabs is the following:
public void UpdateTabs(ObservableCollection<UserAction> list)
{
MainTabBar.Items.Clear();
foreach (UserAction action in list)
{
MainTabBar.Items.Add(new ShellContent()
{
Title = action.Title,
Icon = action.ImageSource,
ContentTemplate = new DataTemplate(() => action.ActionPage),
Route = action.Title
});
}
}
After this method is executed the MainTabBar.Items list has the correct shellcontents in it, however the Tabs are not displayed in the UI. How could I achieve this?
Also, I am aware of the similarities between this and a question asked by User Bagroy (How dynamically add tabs in code behind to Maui Shell TabBar?) but the solutions given in response to his question do not work for me.
Based on the code, seems that using MainTabBar.Items.Clear(); then Tabbar not display.
So the workaround here is to add this code after clear the Items,
MainTabBar.Items.Clear();
//add the following two lines
MainTabBar = new TabBar();
this.Items.Add(MainTabBar);
Hope it works for you.

Shell navigation throws System.ArgumentException: 'Ambiguous routes matched for: ... error

I'm trying to navigate back from the page I have been routed. I have registered all pages as well.
I have Home Page with List view. When clicking ListView Item I'm navigation to DetailsPage from there again I'm navigating to RecordPage. Now when I'm clicking back button on RecordPage, which comes automatically, it throws this exception.
Here is what I have done
AppShell.xaml
<Shell
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MyApp.Mobile.UI;assembly=MyApp.Mobile.UI"
Shell.FlyoutBehavior="Disabled">
<ShellContent
ContentTemplate="{DataTemplate local:HomePage}"
Route="InspectionListPage" />
</Shell>
App.xaml.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
Routing.RegisterRoute(nameof(LoginPage), typeof(LoginPage));
Routing.RegisterRoute(nameof(HomePage), typeof(HomePage));
Routing.RegisterRoute(nameof(DetailsPage), typeof(DetailsPage));
Routing.RegisterRoute(nameof(RecordPage), typeof(RecordPage));
}
}

Navigate between tabs using the back button

I am trying to create my first Xamarin mobile application, I am a bit confused when it comes to navigating back to the previous screen/tab using the back button (android). I have created a test project and I am using Xamarin form shell to define the hierarchy.
The navigation type I am using is Tab. In my test application I got 2 tabs
This is my current method which I am using to navigate back to the first tab from the second tab if the user presses on the back button.
I override OnBackButtonPressed method and execute a command that executes GoTo method.
public partial class ItemsPage : ContentPage
{
ItemsViewModel _viewModel;
public ICommand goBack;
public ItemsPage()
{
InitializeComponent();
BindingContext = _viewModel = new ItemsViewModel();
goBack = new Command(async (x) => await Shell.Current.GoToAsync("////AboutPage"));
}
protected override void OnAppearing()
{
base.OnAppearing();
_viewModel.OnAppearing();
}
protected override bool OnBackButtonPressed()
{
base.OnBackButtonPressed();
goBack.Execute(null);
return true;
}
}
This works, but the problem is, I have hardcoded the page I wanna go back to. In the future, I will be adding 2 more tabs, so in that case say for example if the user is on the 4th tab and the previous tab was Tab 3, how can I retrieve that information so that I can successfully navigate the user back to that previous tab or page?
I tried to use the navigationstack in the Shell but couldn't figure out how to use it with tabs.
Thank you for your time.
Cheers
Edit
-Code in the AppShell which defines the hierarchy
<?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:local="clr-namespace:TestApp03.Views"
Title="TestApp03"
x:Class="TestApp03.AppShell">
<TabBar>
<ShellContent Title="About" Icon="icon_about.png" Route="AboutPage" ContentTemplate="{DataTemplate local:AboutPage}" />
<ShellContent Title="Browse" Icon="icon_feed.png" ContentTemplate="{DataTemplate local:ItemsPage}" />
</TabBar>
</Shell>
You can use await Shell.Current.GoToAsync(".."); to achieve forward jump. For more usage, please refer to this link: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/tabs

Xamarin form: Can Add tabs in Shell App programmatically on the contentpage

I finding through the google but could not find the result.
I have a Shell setup Xamarin form application. Eventhough I am not fully use it's functionally but there is a tab setup in xaml file.
I am wonder can i have a content page hosted under the shellContent and add Tabs from the contentPage.
Do you want to achieve it like this GIF?
You can add x:Name for TabBar in AppShell.xml like this code.
<TabBar x:Name="myTabBars">
<Tab Title="Browse" Icon="tab_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</Tab>
<Tab Title="About" Icon="tab_about.png">
<ShellContent ContentTemplate="{DataTemplate local:AboutPage}" />
</Tab>
</TabBar>
In the AppShell.xml.cs, expose this tabbar.
public partial class AppShell : Xamarin.Forms.Shell
{
// public static Shell myshell;
public static TabBar mytabbar;
public AppShell()
{
InitializeComponent();
mytabbar = myTabBars;
}
}
Use it in the ContentPage.
private void Button_Clicked(object sender, EventArgs e)
{
ShellSection shell_section = new ShellSection
{
Title = "home",
};
shell_section.Items.Add(new ShellContent() { Content = new HomePage() });
AppShell.mytabbar.Items.Add(shell_section);
}

Xamarin.Forms Prism app not showing Master-Detail navigation bar

I am trying to get Master-Detail navigation configured in my Xamarin.Forms app with my UWP target running on Windows 10.
When I run the sample Master-Detail app provided by Xamarin (following https://developer.xamarin.com/guides/xamarin-forms/user-interface/navigation/master-detail-page/), and change the MasterBehavior to Popover, I see the following behavior:
Startup:
Select the hamburger icon:
Make a selection:
In my prism app, I navigate to MainPage/View1:
protected override void OnInitialized()
{
InitializeComponent();
var task = NavigationService.NavigateAsync("MainPage/View1");
...
}
MainPage is my MasterDetailPage with the MasterBehavior set to Popover, and View1 is a ContentPage.
MainPage:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:My.Mobile.Application.Views;assembly=My.Mobile.Application"
x:Class="My.Mobile.Application.Frame.MainPage"
MasterBehavior="Popover">
<MasterDetailPage.Master>
<views:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<views:View1 />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
View1:
public View1()
{
NavigationPage.SetHasNavigationBar(this,false);
InitializeComponent();
}
On startup, I do not see any navigation bar, just the contents of View1 (currently just a red screen):
If I change the MasterBehavior of MainPage.xaml to Default instead of Popover, and remove the SetHasNavigationBar in View1, I see the side menu when the app launches:
MainPage:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:My.Mobile.Application.Views;assembly=My.Mobile.Application"
x:Class="My.Mobile.Application.Frame.MainPage"
MasterBehavior="Default">
<MasterDetailPage.Master>
<views:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<views:View1 />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
View1:
public View1()
{
//NavigationPage.SetHasNavigationBar(this,false);
InitializeComponent();
}
When I make a selection after startup with MasterBehavior set to Default, I now see the hamburger menu.
Is there anything that I can add or verify in my solution to mimic the Xamarin sample behavior with the MasterBehavior set to Popup?
The problem is here: var task = NavigationService.NavigateAsync("MainPage/View1");
Since you want to show the hamburger menu, you need to wrap your Detail in a NavigationPage. So first register a NavigationPage for navigation
Container.RegisterTypeForNavigation<NavigationPage>();
Then add it to your navigation path:
var task = NavigationService.NavigateAsync("MainPage/NavigationPage/View1");
Also, you can remove a the detail markup in your MasterPage XAML because the navigation service will build it up for you.
Try to do something like this:
public partial class ShellView : MasterDetailPage, IMasterDetailPageOptions
{
public ShellView()
{
InitializeComponent();
}
public bool IsPresentedAfterNavigation
{
get { return Device.Idiom != TargetIdiom.Phone; }
}
}

Resources