0
votes

thanks for your help in advance. I am working on a Forms Shell App a few days now. My UI is data driven in a lot of aspects and what I am trying to accomplish ist a page that show multiple tabs on tob depending on the model it has.

In other words I try to accomplish the same layout as in the Shells Demo app:

<FlyoutItem Route="animals"
            Title="Animals"
            FlyoutDisplayOptions="AsSingleItem">
    <Tab Title="Domestic"
         Route="domestic"
         Icon="paw.png">
        <ShellContent Route="cats"
                      Style="{StaticResource DomesticShell}"
                      Title="Cats"
                      Icon="cat.png"
                      ContentTemplate="{DataTemplate views:CatsPage}" />
        <ShellContent Route="dogs"
                      Style="{StaticResource DomesticShell}"
                      Title="Dogs"
                      Icon="dog.png"
                      ContentTemplate="{DataTemplate views:DogsPage}" />
    </Tab>
</FlyoutItem>

But starting from an existing link in the FlyoutMenu. Like the level of the "Domestic" tab above, which when navigatet to creates those two or more Shell top tapped pages.

I am aware I could use a TappedPage as ShellContent, but TappedPages get styled a little different I was wondering if i could accomplish this with "native" Shell features.

I already tried something like:

ShellSection tab1 = new ShellSection
{
Title = "Tab1"
};
tab1.Items.Add(new ShellContent() { Title = "Test1", Content = new ContentPage() { Title = "Test1" } });
tab1.Items.Add(new ShellContent() { Title = "Test2", Content = new ContentPage() { Title = "Test2" } });
var current = AppShell.Current.CurrentItem;
current.Items.Add(tab1);

but this also adds another entry in the bottom tabs bar and the flyout menu as well, what i don't want.

To be more clear I try to explain it with mockup screenshots.

Asume we have the following flyoutmenu where Domestic entry.

enter image description here

This domestic entry leads to a page whichs viewmodel provides a collection of data that should be displayed in tabs.

enter image description here

As you see, this pages provides a Link in the title view which opens a popup to change the selected element and should refresh/change the displayed data for example to have three tabs.

enter image description here

I hope its more clear now.

EDIT:

The comments till now brought me one step further. With the following code I accomplish to get the desired top tabs.

        var current = AppShell.Current.CurrentItem;
        var currentSection = current.CurrentItem;

        //currentSection.Items.Clear();
        currentSection.Items.Add(new CatsPage() { Title = "Tab1"} ); ;
        currentSection.Items.Add(new ShellContent() { Title = "Tab2", Content = new CatsPage() });

enter image description here

But its still not perfect - in the added pages the botton tab bar is hidden, any solution for that?

enter image description here Has someone an advice?

2

2 Answers

0
votes

Do you mean you want to achieve the same structure as in the Shell demo app by behind codes ?

If yes,you could try this :

in AppShell.xaml.cs:

public AppShell()
    {
        InitializeComponent();
        FlyoutItem shellItem = new FlyoutItem() { Title = "Tab1" };
        Tab tab = new Tab();
        tab.Items.Add(new ShellContent() { Title = "Test1", Content = new Page1()});
        tab.Items.Add(new ShellContent() { Title = "Test2", Content = new Page2()});
        shellItem.Items.Add(tab);
        this.Items.Add(shellItem);
    }

AppShell.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"
   mc:Ignorable="d"
   xmlns:local="clr-namespace:ShellDemo.Views"
   Title="ShellDemo"
   x:Class="ShellDemo.AppShell">

</Shell>

page1.xaml:

<ContentPage ...>
    <Shell.TitleView>
      <Button Text="change" Clicked="Button_Clicked"></Button>
    </Shell.TitleView>
     ...
</ContentPage>

in page1.xaml.cs:

private void Button_Clicked(object sender, EventArgs e)
    {
        Tab tab = new Tab();
        tab.Items.Add(new ShellContent() { Title = "Test3", Content = new ContentPage() { Title = "Test3" } });
        tab.Items.Add(new ShellContent() { Title = "Test4", Content = new ContentPage() { Title = "Test4" } });
        AppShell.Current.CurrentItem.Items.Clear();
        AppShell.Current.CurrentItem.Items.Add(tab);
    }

Update1:

from your sketches above,do you want to change the TabbedPage content after click the link in titleview ()?

the effec is like below (you should add shell titileview in every page,here use buttons instead of the link):

enter image description here

Update 1 you only need to change the tab's contents:

 private void Button_Clicked(object sender, EventArgs e)
    {
        Tab tab = (Tab)AppShell.Current.CurrentItem.CurrentItem;
        tab.Items.Clear();
        tab.Items.Add(new ShellContent() { Title = "Test3", Content = new ContentPage() { Title = "Test3" } });
        tab.Items.Add(new ShellContent() { Title = "Test4", Content = new ContentPage() { Title = "Test4" } });

    }

Update 2:

I download your project and test it.It doesn't actually hide the bottom Tab, you can click on the bottom Tab and see that it exists, but it doesn't have a background color, so you just give it the Style that defined in Shell.Resources when you add ShellContent

 var current = AppShell.Current.CurrentItem;
 var currentSection = current.CurrentItem;
 currentSection.Items.Add(new ShellContent() { Title = "Test3", Content = new CatsPage(),Style = (Style)AppShell.Current.Resources["BearsShell"] }); ;
 currentSection.Items.Add(new ShellContent() { Title = "Test4", Content = new CatsPage(), Style = (Style)AppShell.Current.Resources["BearsShell"] });
0
votes

This solution also includes the usage of the ContentTemplate in code:

AppShell.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"
    x:Class="Namespace.To.AppShell.xaml.cs"
    FlyoutBehavior="True" />

AppShell.xaml.cs

public AppShell()
{
    this.InitializeComponent();

    var flyoutTabOne = new Tab()
    {
        Items =
        {
            new ShellContent
            {
                ContentTemplate = new DataTemplate(() => new YourPage()),
                Route = "Route.To.Your.Page",
                Title = "Your page title",
            },
        },
        Route = "Route.To.Your.Tab.One",
        Title = "Tab one title",
    };

    var flyoutItem = new FlyoutItem();
    flyoutItem.Items.Add(flyoutTabOne);

    this.Items.Add(flyoutItem);
}

The usage of ContentTemplate is important to obtain lazy loading of all tabs. Therefore I strongly recommend to use a ContentTemplate whenever possible and as it was already the case in the opening question (in xaml). If you are interested in more information about the ContentTemplate, please read this documentation: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/shell/tabs#efficient-page-loading