3

In Xamarin Shell I'm trying to add a header to a flyout item. See the picture below (taken from the Xaminals project).

The 'Categories' text is a header which is not clickable or navigatable, just a static template.

I have found an article here but it's without source code and I haven't been able to construct a working example.

How can I achieve something like this?

enter image description here

Jasper
  • 545
  • 7
  • 18
  • you can get code from here https://github.com/xamarin/xamarin-forms-samples/tree/master/UserInterface/Xaminals/Xaminals – Himanshu Dwivedi Dec 02 '19 at 11:57
  • 1
    That is the Xaminals project but that's not what I'm looking for. I was using the Xaminals project as a base to extend it to what I want in the description above. – Jasper Dec 02 '19 at 12:21

2 Answers2

1

I managed to figure out a solution, so I'll put it here in case anyone wants something similar.

  1. Add a FlyoutItemTemplateSelector. This class will be responsible for rendering a regular flyout item or a header template.

    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;
        }
    }
    
  2. Add the regular ItemTemplate, the new Header template and the FlyoutItemTemplateSelector control to the Shell.Resources tag in AppShell.xaml:

    <Shell.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="FlyoutItemTemplate">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="0.25*" />
                        <ColumnDefinition Width="0.75*" />
                    </Grid.ColumnDefinitions>
                    <Label Text="{Binding Icon}"
                           FontFamily="{StaticResource MaterialFontFamily}"
                           HeightRequest="45"
                           Margin="20,0,0,0"
                           FontSize="30"
                           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 HeightRequest="35"
                           Margin="20,0,0,0"
                           Text="{Binding Title}"
                           TextColor="Black"
                           VerticalTextAlignment="Center" />
                </StackLayout>
            </DataTemplate>
    
            <controls:FlyoutItemTemplateSelector
                x:Key="FlyoutTemplateSelector"
                NavigationHeaderTemplate="{StaticResource FlyoutHeaderTemplate}"
                NavigationItemTemplate="{StaticResource FlyoutItemTemplate}" />
        </ResourceDictionary>
    </Shell.Resources>
    
  3. Add the Shell.ItemTemplate to the main Shell tag:

    <Shell
        ...
        Shell.ItemTemplate="{StaticResource FlyoutTemplateSelector}"
    >
    
  4. Add the item for the header:

    <ShellContent Title="Header" ContentTemplate="{DataTemplate local:AboutPage}" />
    

Result:

enter image description here

Some notes:

  • We can't remove the ContentTemplate attribute for the header item, so we must add a dummy one. I should look into that later
  • Make sure the Title attribute is set to "Header". The FlyoutItemTemplateSelector control will identify this as a header template.

Like this, we can also define other templates, like a footer containing your app version, or a copyright text, etc...

Hope this helps anyone.

Jasper
  • 545
  • 7
  • 18
1

You can use a MenuItem instead of ShellContent to achieve this. Menu item has a clicked event and command property, but if you don't bind to a command, you can effectively create a section header that does nothing when clicked. See: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/flyout#menu-items

<Shell
 ..
   <Shell.MenuItemTemplate>
     <DataTemplate>
      <!-- Layout for menu item to differentiate from clickable flyout items -->
    </DataTemplate>
   </Shell.MenuItemTemplate>

  <MenuItem Text="Section Header">
  <FlyoutItem .../>
  <ShellContent .../>
..
</Shell>


tdipiazza
  • 11
  • 1