According to your description, you want to add sub menu item in Shell one menu item.
Firstly, I create DataTemplateSelector
, to detect menu item title is Header
or other, if it is Header, choose NavigationHeaderTemplate
, then choosing NavigationItemTemplate
.
public class FlyoutItemTemplateSelector : DataTemplateSelector
{
public DataTemplate NavigationHeaderTemplate { get; set; }
public DataTemplate NavigationItemTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is ShellGroupItem && ((ShellGroupItem)item).Title == "Header")
{
// Make sure a header item is not clickable.
((ShellGroupItem)item).IsEnabled = false;
return NavigationHeaderTemplate;
}
else
return NavigationItemTemplate;
}
}
Then adding the regular ItemTemplate, the new Header template and the FlyoutItemTemplateSelector control to the Shell.Resources tag in AppShell.xaml:
<DataTemplate x:Key="FlyoutItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.25*" />
<ColumnDefinition Width="0.75*" />
</Grid.ColumnDefinitions>
<Label
Margin="20,0,0,0"
FontSize="30"
HeightRequest="45"
Text="{Binding Icon}"
TextColor="Black"
VerticalTextAlignment="Center" />
<Label
Grid.Column="1"
Text="{Binding Title}"
TextColor="Black"
VerticalTextAlignment="Center" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="FlyoutHeaderTemplate">
<StackLayout Orientation="Vertical">
<Label
Margin="20,0,0,0"
HeightRequest="35"
Text="{Binding Title}"
TextColor="Black"
VerticalTextAlignment="Center">
<Label.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</DataTemplate>
<controls:FlyoutItemTemplateSelector
x:Key="FlyoutTemplateSelector"
NavigationHeaderTemplate="{StaticResource FlyoutHeaderTemplate}"
NavigationItemTemplate="{StaticResource FlyoutItemTemplate}" />
Add the Shell.ItemTemplate to the main Shell tag.
<Shell
x:Class="shellsample.AppShell"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:shellsample"
xmlns:local="clr-namespace:shellsample.Views"
Title="shellsample"
Shell.ItemTemplate="{StaticResource FlyoutTemplateSelector}">
Finally, using FlyoutItem.
<FlyoutItem
Title="About"
FlyoutDisplayOptions="AsMultipleItems"
Shell.TabBarIsVisible="False">
<ShellContent Title="Header" ContentTemplate="{DataTemplate local:AboutPage}" />
<ShellContent
Title="sub1"
ContentTemplate="{DataTemplate local:AboutPage}"
IsVisible="{Binding isvisible}" />
<ShellContent
Title="sub2"
ContentTemplate="{DataTemplate local:AboutPage}"
IsVisible="{Binding isvisible}" />
<ShellContent
Title="sub3"
ContentTemplate="{DataTemplate local:AboutPage}"
IsVisible="{Binding isvisible}" />
</FlyoutItem>
<FlyoutItem Title="Browse" Icon="icon_feed.png">
<ShellContent ContentTemplate="{DataTemplate local:ItemsPage}" />
</FlyoutItem>
public partial class AppShell : Xamarin.Forms.Shell, INotifyPropertyChanged
{
private bool _isvisible;
public bool isvisible
{
get { return _isvisible; }
set
{
_isvisible = value;
OnPropertyChanged("isvisible");
}
}
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute(nameof(ItemDetailPage), typeof(ItemDetailPage));
Routing.RegisterRoute(nameof(NewItemPage), typeof(NewItemPage));
this.BindingContext = this;
}
private async void OnMenuItemClicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//LoginPage");
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected override void OnNavigating(ShellNavigatingEventArgs args)
{
base.OnNavigating(args);
}
private void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
isvisible = !isvisible;
}
}
Please note: using Xamarin.forms version 4.8.0.1821
The screenshot:

